list - 带有 Toggle 和 NavigationLink 的 SwiftUI onDelete 列表
问题描述
我指的是我已经问过的两个问题,Asperi 已经很好地回答了:SwiftUI ForEach with .indices() does not update after onDelete, SwiftUI onDelete List with Toggle
现在我尝试ForEach
用 a修改闭包NavigationLink
,突然应用程序再次崩溃
Thread 1: Fatal error: Index out of range
当我尝试滑动删除时。
代码:
class Model: ObservableObject {
@Published var name: String
@Published var items: [Item]
init(name: String, items: [Item]) {
self.name = name
self.items = items
}
}
struct Item: Identifiable {
var id = UUID()
var isOn: Bool
}
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
List {
ForEach(model.items) {item in
NavigationLink(destination: DetailView(item: self.makeBinding(id: item.id))) {
Toggle(isOn: self.makeBinding(id: item.id).isOn)
{Text("Toggle-Text")}
}
}.onDelete(perform: delete)
}
}
}
func delete(at offsets: IndexSet) {
self.model.items.remove(atOffsets: offsets)
}
func makeBinding(id: UUID) -> Binding<Item> {
guard let index = self.model.items.firstIndex(where: {$0.id == id}) else {
fatalError("This person does not exist")
}
return Binding(get: {self.model.items[index]}, set: {self.model.items[index] = $0})
}
}
struct DetailView: View {
@Binding var item: Item
var body: some View {
Toggle(isOn: $item.isOn) {
Text("Toggle-Text")
}
}
}
它没有NavigationLink
OR 没有Toggle
. 所以在我看来,我只能makeBinding
在这个闭包中使用 -Function 一次。
感谢帮助
解决方案
无论有没有导航链接,您的代码都会对我崩溃。有时只有当我删除数组中的最后一个对象时。看起来它仍在尝试从数组中访问索引。您在上面链接的示例的不同之处在于它们不用于EnvironmentObject
访问数组。将数组直接存储在@State
.
我想出了一些不同的方法,将 Item 声明为ObservedObject
,然后简单地将其传递给子视图,您可以在其中将它们的值用作绑定,而无需任何功能。
我将项目更改为..
class Item: ObservableObject {
var id = UUID()
var isOn: Bool
init(id: UUID, isOn: Bool)
{
self.id = id
self.isOn = isOn
}
}
将 ContentView 更改为此..
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
List {
ForEach(model.items, id:\.id) {item in
NavigationLink(destination: DetailView(item: item)) {
Toggler(item: item)
}
}.onDelete(perform: delete)
}
}
}
我将 Toggle 外包给了另一个视图,我们将 ObservedObject 传递给,DetailView 也是如此。
struct Toggler: View {
@ObservedObject var item : Item
var body : some View
{
Toggle(isOn: $item.isOn)
{Text("Toggle-Text")}
}
}
struct DetailView: View {
@ObservedObject var item: Item
var body: some View {
Toggle(isOn: $item.isOn) {
Text("Toggle-Text")
}
}
}
它们都采用Item
as ObservedObject 并将其用作Toggle
.
推荐阅读
- android - 清除活动 Android
- javascript - 如何将唯一的可访问/可传递值烘焙到多个显示按钮中?
- r - 无法使用 R 的 tm 中的 DataframeSource 从数据帧中获取元数据
- html - 单击带有一些动画效果的li元素如何从底部缓慢移动到顶部位置
- python - 如何保存来自 python 循环的不同名称的多个绘图?
- maven - 删除万能插件
- docker - 如何使用 docker 配置 Corda 网络(使用 YAML 文件)
- c# - C# - Asp.net Web API 测试项目 - 如何模拟用户并在特定用户下运行测试用例
- c# - log4net.Appender 中缺少 AdoNetAppender 类
- spring-boot - 使用 H2 和 JPA 的 Spring Boot 集成测试失败