SwiftUI:为什么此绑定更改不会重新呈现视图?

时间:2020-03-17 17:42:13

标签: swiftui

下面是一个更复杂的应用程序的精炼示例。 RootModel有一个Items数组,每个Item有一个text属性。我的UI使用NavigationView来推送根模型,项目和文本的视图。

在下面的示例代码中,如果我创建一个项目并编辑其文本,则TextEditor视图不会重新呈现。如果弹出,则表明模型已正确更改。当我在TextEditor视图中点击“随机更改”按钮时,为什么不重新渲染?

我不想将所有内容都变成ObservableObject。对于根对象我可以接受,但是Swift对于不可变的值类型和协议非常有效,并且我不想为了使模型的每个部分都成为可变对象而放弃它。

struct Item {
    var text: String = ""
}

class RootModel: ObservableObject {
    @Published var items: [Item] = []
}

struct ContentView: View {
    @ObservedObject var model: RootModel
    @State private var isEditItemActive = false
    /// Add a state var to say which item we're editing.
    @State private var editingIndex: Int = -1

    var body: some View {
        NavigationView {
            VStack {
                Text("View of RootModel object")
                HStack {
                    Text("Items")
                    Spacer()
                    Button(action: self.addItem) {
                        Text("Add")
                    }
                }
                ForEach(model.items.indices, id: \.self) { idx in
                    HStack {
                        Text("Item: \(self.model.items[idx].text)")
                        Image(systemName: "chevron.right")
                    }.onTapGesture {
                        self.editItem(index: idx)
                    }
                }
                Button(action: self.deleteAllItems) {
                    Text("Delete all items")
                }
                NavigationLink(destination: EditItemView(array: $model.items, index: $editingIndex),
                               isActive: $isEditItemActive) {
                   EmptyView()
                }
                Spacer()
            }
            .padding()
            .navigationBarTitle("Root", displayMode: .inline)
        }
    }

    private func deleteAllItems() {
        model.items.removeAll()
    }

    private func addItem() {
        let num = Int.random(in: 10000...20000)
        let newItem = Item(text: "\(num)")
        model.items.append(newItem)
        editItem(index: model.items.count-1)
    }

    private func editItem(index: Int) {
        print("edit \(index)")
        editingIndex = index
        isEditItemActive = true
    }
}

struct EditItemView: View {

    @Binding var array: [Item]
    @Binding var index: Int

    @State private var isTextEditorPushed = false

    var body: some View {
        VStack {
            Text("Editing item")
            Text("Text: \(array[index].text)")
            Button(action: self.editText) {
                Text("Edit item.text")
            }
            NavigationLink(destination: TextEditor(text: $array[index].text),
                           isActive: $isTextEditorPushed) {
                 EmptyView()
            }
            Spacer()
        }
    }

    private func editText() {
        isTextEditorPushed = true
    }
}

struct TextEditor: View {
    @Binding var text: String
    var body: some View {
        VStack {
            Text("Editing item.text:")
            Text("Text: \(text)")
            Button(action: self.changeText) {
                Text("Randomly change it")
            }
        }
    }
    private func changeText() {
        let n = Int.random(in: 10000...20000)
        print("changeText: \(n)")
        text = "\(n)"
    }
}

0 个答案:

没有答案