SwiftUI .onDelete throws Fatal Error: Index out of range
SwiftUI .onDelete throws Fatal Error: Index out of range
我有 Account
个列表,每个列表都有一个详细信息页面,它们通过 AccountDetailView
中的 @Binding
连接。当前代码运行良好,更新很好。完全没有问题。但是,当我将 onDelete
修饰符添加到下面的 ForEach
并尝试在应用程序中使用 swipe to delete
手势时,它崩溃并显示 Fatal Error: Index out of range
两次。
我进行了一些搜索,了解到 ForEach
不知何故没有收到通知 - 或者忽略它,idk 很多细节 - 并查找数组的最后一个索引。最后,它找不到它并抛出错误。
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
class 符合 Codable
、NSObject
、Indentifiable
和其他一些 class。我不想给出所有的代码只是因为不想让问题变得复杂和难以检查。如果需要,我将提供代码的任何部分。提前致谢。
找到解决办法。关于这个 到一个相关问题,它很清楚。显然,使用 .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)!] = [=12=]
}
}
}
这样,onDelete
和通过直接更新详细视图中的对象来发布更改都将起作用。
我有 Account
个列表,每个列表都有一个详细信息页面,它们通过 AccountDetailView
中的 @Binding
连接。当前代码运行良好,更新很好。完全没有问题。但是,当我将 onDelete
修饰符添加到下面的 ForEach
并尝试在应用程序中使用 swipe to delete
手势时,它崩溃并显示 Fatal Error: Index out of range
两次。
我进行了一些搜索,了解到 ForEach
不知何故没有收到通知 - 或者忽略它,idk 很多细节 - 并查找数组的最后一个索引。最后,它找不到它并抛出错误。
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
class 符合 Codable
、NSObject
、Indentifiable
和其他一些 class。我不想给出所有的代码只是因为不想让问题变得复杂和难以检查。如果需要,我将提供代码的任何部分。提前致谢。
找到解决办法。关于这个 .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)!] = [=12=]
}
}
}
这样,onDelete
和通过直接更新详细视图中的对象来发布更改都将起作用。