我有Account
个列表,每个列表都有一个详细页面,它们通过@Binding
中的AccountDetailView
连接。当前代码运行良好,更新很好。没问题但是,当我将onDelete
修饰符添加到下面的ForEach
并尝试在应用程序中进行swipe to delete
手势时,它崩溃并说两次Fatal Error: Index out of range
。
我进行了一些搜索,发现ForEach
不会以某种方式得到通知-或将其忽略,详细信息-并查找数组的最后一个索引。最后,它找不到它并引发错误。
List {
Section(header: Text(String.empty), footer: Text(Strings.SectionFooters.accountListFooter.value)) {
ForEach(self.accountsModel.accounts.indices, id:\.self) { idx in
NavigationLink(destination: AccountDetailView(account: self.$accountsModel.accounts[idx])) {
AccountRow(account: self.$accountsModel.accounts[idx])
}
}.onDelete { (set) in
self.accountsModel.accounts.remove(atOffsets: set)
}
}
}
将id: \.self
参数保持在适当的位置会在AppDelegate
处引发错误,当我尝试删除该参数时,该应用程序可以正常运行,但是onDelete
仍会在该位置抛出相同的错误NavigationLink
的行。
这里是AccountDetailView
struct AccountDetailView: View {
@EnvironmentObject var accountsModel: AccountsViewModel
@Binding var account: Account
@State var isEditing: Bool = false
var body: some View {
...
}
}
最后Account
类符合Codable
,NSObject
,Indentifiable
和其他某个类。我不想给出所有代码,只是因为不想使问题复杂且难以检查。如果需要,我将提供代码的任何部分。预先感谢。
答案 0 :(得分:0)
找到了解决方案。关于这个answer的相关问题,这一点很明确。适当地,使用.indices
填充ForEach
会使onDelete
无法正常工作。相反,直接遍历数组的Elements
并创建代理Bindings
是可行的。
更清楚地说,这里是ContentView
,DetailView
和Binding
的扩展名,以避免视图混乱。
ContentView
struct ContentView: View {
@EnvironmentObject var store: DataStore
var body: some View {
NavigationView {
List {
ForEach(self.store.data, id: \.id /*with or without id*/) { (data) in
NavigationLink(destination: DetailView(data: /*created custom initializer*/ Binding(from: data))) {
Text(data.name)
}
}.onDelete { (set) in
self.store.data.remove(atOffsets: set)
}
}.navigationBarTitle("List")
}
}
}
DetailView
struct DetailView: View {
@Binding var data: MyData
var body: some View {
List {
TextField("name", text: self.$data.name)
}
.navigationBarTitle(self.data.name)
.listStyle(GroupedListStyle())
}
}
Binding
扩展名
extension Binding where Value: MyData {
init(from data: MyData) {
self.init(get: {
data as! Value
}) {
dataStore.data[dataStore.data.firstIndex(of: data)!] = $0
}
}
}
通过这种方式,onDelete
和通过直接更新详细信息视图内的对象来发布更改都将起作用。