Переплет ломается при представлении .shee - но где и почему?IOS

Программируем под IOS
Ответить
Anonymous
 Переплет ломается при представлении .shee - но где и почему?

Сообщение Anonymous »

a swiftui View должен показывать разные .sheet s. Например, некоторые EditorView с представлением сбора в. И.class Router: ObservableObject {
@Published var sheetContent: AnyView? = nil

func present(content: Content) {
self.sheetContent = AnyView(content)
}
}

struct RouterView: View {
@ObservedObject var router: Router

private var content: () -> Content

init (_ router: Router, @ViewBuilder content: @escaping () -> Content) {
self.router = router
self.content = content
}

var body: some View {
content()
.sheet(isPresented: Binding(
get: { router.sheetContent != nil },
set: { if !$0 { router.sheetContent = nil } }
)) {
router.sheetContent
}
}
}

Хотя это хорошо работает в целом, он каким -то образом ломает @binding s, используемый в представленном контенте, как в демо -коде ниже.
Демо включает в себя: < /strong> < /p>
  • RouterTestView Удерживание ViewModel с его экземпляром маршрутизатора . Он показывает текущее значение viewmodel.showtitle < /code> и кнопок, чтобы показать лист тремя различными способами:

    Настройка «классическая» лист «классический» и контролируется в представлении < /li>
    Управляемый лист маршрутизатора, в котором контент создается в ViewModel < /li>
    Лист, управляемый маршрутизатором, где контент создается в пределах Просмотр < /li>
    < /ul>
    < /li>
    Ожидаемое поведение:

    Независимо от того, какой лист используется, отображается значение valueView . />$ viewmodel.showtitle может быть переключен. Изменение показано в RouterTestView и в ValueView


[*] Фактическое поведение: < Br />
Только классический лист работает, как и ожидалось. $ viewmodel.showtitle правильно применяется к ViewModel. При закрытии листового маршрутизатора правильно показывает true или false. При представлении другого листа начальное состояние (скрытое/видимое) заголовка является правильным.
Однако переключение не сразу применяется к значению . Текст заголовка не изменяет свою видимость. < /Li>
< /ul>
< /li>
< /ul>
Заключение: < /strong> с использованием маршрутизатора каким -то образом нарушает привязку он работает только из valueview обратно в ViewModel , в то время как другое направление (viewModel to valueview ) не работает.
Как это можно решить? [/b]


демо -код: < /strong> < /p>
// View Model
extension RouterTestView {
class ViewModelModel: ObservableObject {
@Published var router = Router()

@Published var title: String = "The Value"
@Published var showTitle: Bool = true

func show() {
router.present(content: ValueView(value: title, showValue: Binding(get: { self.showTitle }, set: { self.showTitle = $0 })))
}

func show(_ inView: Content) {
router.present(content: inView)
}
}
}

struct RouterTestView: View {
@StateObject var viewModel: ViewModelModel = .init()

@State private var isPresentingSheet: Bool = false

var body: some View {
Text("showTitle == \(viewModel.showTitle ? "true" : "false")")

// Do not use Router but instead use the classic way to present
// the sheet. The Binding works without any problem.
Button("Present Sheet manually") {
isPresentingSheet = true
}
.padding()
.sheet(isPresented: $isPresentingSheet) {
ValueView(value: viewModel.title, showValue: $viewModel.showTitle)
}

// Use Router to present the sheet. It makes no difference if the
// Content is created in the ViewModel or here. The Binding is broken.
// Changes to $viewModel.showTitle in ValueView are correctly reported
// to the viewModel, but the changes are not recognized in ValueView
// itself
RouterView(viewModel.router) {
// Sheet with Content created in viewModel
Button("Present Sheet with Router") {
viewModel.show()
}
.padding()

// Sheet with Content created here.
Button("Present Sheet with Router") {
viewModel.show(
ValueView(value: viewModel.title, showValue: $viewModel.showTitle)
)
}
.padding()
}
}
}

// ValueView as dummy "editor". Changes in the showValue Binding should be reported
// Back to the viewModel in RouterTestView and toggle the visibility of the value here.
struct ValueView: View {
let value: String
@Binding var showValue: Bool

var body: some View {
Text("Here is the value:")

if showValue {
Text(value)
}

Button("Toggle") {
showValue.toggle()
}
}
}

#Preview {
RouterTestView()
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... re-and-why
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»