SwiftUI: Почему это изменение привязки не перерисовывает представление? - PullRequest
0 голосов
/ 17 марта 2020

Ниже приведен пример из более сложного приложения. RootModel имеет массив Items, а каждый Item имеет свойство text. Мой пользовательский интерфейс использует NavigationView to pu sh представлений root модели, элемента и затем текста.

В приведенном ниже примере кода, если я создаю элемент и редактирую его текст, представление TextEditor не отображается повторно. Если я возвращаюсь назад, я вижу, что модель изменилась правильно. Почему он не рендерится повторно, когда я нажимаю кнопку «Случайно изменить его» в представлении TextEditor?

Я не хочу превращать все в ObservableObject. Я согласен с этим для root объектов, но 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)"
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...