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

Posted

技术标签:

【中文标题】如何将 SwiftUI 视图绑定到数组中元素的属性【英文标题】:How to bind a SwiftUI view to properties of an element in an array 【发布时间】: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,因此我们将不胜感激。

【问题讨论】:

【参考方案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()
    

【讨论】:

谢谢。说得通。将在星期二尝试并将其标记为正确。

以上是关于如何将 SwiftUI 视图绑定到数组中元素的属性的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 SwiftUI 视图绑定到嵌套的 ObservableObjects

将 SwiftUI 警报或操作表绑定到值类型模型属性的可选性(当属性为 nil 时显示视图)的好方法是啥?

如何告诉 SwiftUI 视图绑定到多个嵌套的 ObservableObject

在 SwiftUI 中更新/编辑数组元素的最佳方法

如何切换数组中对象的属性并更新 SwiftUI 视图?

如何使用 SwiftUI 将数组绑定到列表