下面是一个更复杂的应用程序的精炼示例。 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)"
}
}