Немного сложно объяснить, в чем проблема. Возможно, проще всего запустить код и отредактировать одну из моделей, а затем посмотреть, что происходит с подробным представлением. Но я попытаюсь объяснить:)
У меня есть представление, в котором я показываю список компьютеров, разбитых на два раздела на основе поля в модели Computer. Вы можете нажать на компьютер, чтобы показать его подробный экран, на котором есть кнопка для редактирования компьютера.
Проблема возникает при редактировании логического значения isLaptop. Допустим, вы открываете iMa c, меняете isLaptop на true и сохраняете форму. На подробном экране все еще написано «Это не ноутбук», хотя теперь он должен сказать «Это ноутбук». Когда вы вернетесь к представлению списка, вы увидите, что список обновлен правильно и iMa c перемещен в раздел «Ноутбуки».
Я предполагаю, что как только я отредактирую поле isLaptop, что DetailView
в основном становится сиротой, поскольку ContentView
воссоздает свое тело, список изменился из-за фильтра, и теперь DetailView
больше не "связан" с тем, что уже на экране. Я думал, что добавление .id(computer.id)
к NavigationLink
поможет, но, к сожалению, это не так.
Итак, как можно сделать так, как ожидается, чтобы отфильтрованный список с двумя его разделами работал, но когда вы изменить поле, которое фильтруется, подпредставления также восстанавливаются правильно, как и ожидалось?
import SwiftUI
struct Computer: Identifiable {
var id: Int
var name: String
var isLaptop: Bool
}
class Store: ObservableObject {
@Published var computers: [Computer] = [
Computer(id: 0, name: "Macbook", isLaptop: true),
Computer(id: 1, name: "iMac", isLaptop: false),
]
}
struct ContentView: View {
@EnvironmentObject private var store: Store
var body: some View {
NavigationView {
List {
Section(header: Text("Laptops")) {
ForEach(store.computers.filter { $0.isLaptop == true }) { computer in
NavigationLink(destination: DetailView(computer: computer)) {
Text(computer.name)
}
}
}
Section(header: Text("Other computers")) {
ForEach(store.computers.filter { $0.isLaptop == false }) { computer in
NavigationLink(destination: DetailView(computer: computer)) {
Text(computer.name)
}
}
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Computers")
}
}
}
struct DetailView: View {
let computer: Computer
@EnvironmentObject private var store: Store
@State private var editing = false
var body: some View {
VStack {
Text(computer.name)
Text(computer.isLaptop ? "This is a laptop" : "This is not a laptop")
}
.navigationBarItems(trailing: Button("Edit") {
self.editing = true
})
.sheet(isPresented: $editing) {
FormView(computer: self.computer)
.environmentObject(self.store)
}
}
}
struct FormView: View {
@EnvironmentObject private var store: Store
@Environment(\.presentationMode) private var presentationMode
@State private var computer: Computer
init(computer: Computer) {
_computer = State(initialValue: computer)
}
var body: some View {
NavigationView {
Form {
TextField("Name", text: $computer.name)
Toggle("Is Laptop", isOn: $computer.isLaptop)
}
.navigationBarTitle("Edit Computer")
.navigationBarItems(trailing: Button("Save") {
self.store.computers = self.store.computers.filter { $0.id != self.computer.id } + [self.computer]
self.presentationMode.wrappedValue.dismiss()
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}