【问题标题】:How to bind a SwiftUI view to properties of an element in an array如何将 SwiftUI 视图绑定到数组中元素的属性
【发布时间】:2020-12-13 17:17:27
【问题描述】:

我在 SwiftUI 中使用 MVVM 架构。

我正在尝试重构我的代码以在我的视图中使用 ForEach() 来显示许多具有相同基本格式的子视图、一个字符串(提出问题)和一个用于显示工作表的按钮输入值。

struct EntryView: View {
    @ObservedObject var viewModel = EntryViewModel()
    var body: some View {
        VStack (spacing: 50) {
            ForEach(viewModel.questions.indices) { index in
                HStack (spacing: 50) {
                    Text(viewModel.questions[index].text)
                        .sheet(isPresented: $viewModel.questions[index].sheetIsPresented,
                                     content: {
                                        viewModel.questions[index].sheet
                                     })
                    Button(action: {
                        viewModel.questions[index].sheetIsPresented = true
                    }, label: {
                        Text("Enter")
                    })
                }
            }
        }
    }
}



class EntryViewModel: ObservableObject {
    @Published var questions: [Question] = []
    @Published var firstQuestion = Question()
    @Published var secondQuestion = Question()
    
    init() {
        questions.append(firstQuestion)
        questions.append(secondQuestion)
    }
}

class Question: ObservableObject {
    @Published var sheetIsPresented = false
    let text = "Foo"
    var sheet = AnyView(InitialView())
}

问题在于,尽管按钮更改了数组中正确索引处正确元素中的正确属性,但这并不会导致视图更新。

我知道这是因为当 questions Array 的 Question 元素的 sheetIsPresented 属性更改为 true 时,它​​实际上并没有改变 Array 本身,因此发布者不会更新视图。

请问如何解决?

我仍在努力了解 SwiftUI 和 Combine,因此我们将不胜感激。

【问题讨论】:

    标签: swift xcode foreach swiftui observableobject


    【解决方案1】:

    你不能“链接” ObservableObjects。您必须直接观察它们。

    import SwiftUI
    
    struct EntryView: View {
        @ObservedObject var viewModel = EntryViewModel()
        var body: some View {
            VStack (spacing: 50) {
                ForEach(viewModel.questions.indices) { index in
                    SingleEntryView(viewModel: viewModel.questions[index])
                }
            }
        }
    }
    struct SingleEntryView: View {
        @ObservedObject var viewModel: Question
        var body: some View {
            HStack (spacing: 50) {
                Text(viewModel.text)
                    .sheet(isPresented: $viewModel.sheetIsPresented,
                                 content: {
                                    viewModel.sheet
                                 })
                Button(action: {
                    viewModel.sheetIsPresented = true
                }, label: {
                    Text("Enter")
                })
            }
        }
    }
    
    
    class EntryViewModel: ObservableObject {
        @Published var questions: [Question] = []
        @Published var firstQuestion = Question()
        @Published var secondQuestion = Question()
        
        init() {
            questions.append(firstQuestion)
            questions.append(secondQuestion)
        }
    }
    
    class Question: ObservableObject {
        @Published var sheetIsPresented = false
        let text = "Foo"
        var sheet = AnyView(Text("Sheet"))
    }
    
    struct EntryView_Previews: PreviewProvider {
        static var previews: some View {
            EntryView()
        }
    }
    

    【讨论】:

    • 谢谢。说得通。将在星期二尝试并将其标记为正确。
    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    相关资源
    最近更新 更多