如何将 SwiftUI 视图绑定到数组中元素的属性

How to bind a SwiftUI view to properties of an element in an array

我在 SwiftUI 中使用 MVVM 架构。

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

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())
}

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

我知道这是因为当问题数组的问题元素的 sheetIsPresented 属性 更改为 true 时,它​​实际上并没有改变数组本身,所以发布者没有更新视图。

请问我该如何解决?

我仍在努力了解 SwiftUI 和 Combine,因此非常感谢收到任何指示。

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

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()
    }
}