gpt4 book ai didi

swift - 从 SwiftUI 的 List 中删除列表元素

转载 作者:行者123 更新时间:2023-12-03 09:22:33 24 4
gpt4 key购买 nike

SwiftUI 似乎有一个相当烦人的限制,使得创建 List 变得困难。或 ForEach同时获取每个元素的绑定(bind)以传递给 subview 。
我见过的最常见的建议方法是迭代索引,并获得与 $arr[index] 的绑定(bind)。 (事实上​​,类似的东西是 suggested by Apple 当他们删除 Binding 的符合 Collection ):

@State var arr: [Bool] = [true, true, false]

var body: some View {
List(arr.indices, id: \.self) { index in
Toggle(isOn: self.$arr[index], label: { Text("\(idx)") } )
}
}
那行得通 直到 数组大小发生变化,然后它因索引超出范围运行时错误而崩溃。
这是一个会崩溃的例子:
class ViewModel: ObservableObject {
@Published var arr: [Bool] = [true, true, false]

init() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.arr = []
}
}
}

struct ContentView: View {
@ObservedObject var vm: ViewModel = .init()

var body: some View {
List(vm.arr.indices, id: \.self) { idx in
Toggle(isOn: self.$vm.arr[idx], label: { Text("\(idx)") } )
}
}
}
处理从列表中删除的正确方法是什么,同时仍然保持使用绑定(bind)修改其元素的能力?

最佳答案

使用来自@pawello2222 和@Asperi 的见解,我想出了一种我认为效果很好的方法,而不会过于讨厌(仍然有点hacky)。
我想让这种方法更通用,而不仅仅是问题中的简化示例,也不是破坏关注点分离的方法。
因此,我创建了一个新的包装 View ,该 View 创建了一个与自身内部的数组元素的绑定(bind)(这似乎根据@pawello2222 的观察修复了状态失效/更新顺序),并将绑定(bind)作为参数传递给内容闭包。
我最初预计需要对索引进行安全检查,但事实证明这个问题不需要。

struct Safe<T: RandomAccessCollection & MutableCollection, C: View>: View {

typealias BoundElement = Binding<T.Element>
private let binding: BoundElement
private let content: (BoundElement) -> C

init(_ binding: Binding<T>, index: T.Index, @ViewBuilder content: @escaping (BoundElement) -> C) {
self.content = content
self.binding = .init(get: { binding.wrappedValue[index] },
set: { binding.wrappedValue[index] = $0 })
}

var body: some View {
content(binding)
}
}
用法是:
@ObservedObject var vm: ViewModel = .init()

var body: some View {
List(vm.arr.indices, id: \.self) { index in
Safe(self.$vm.arr, index: index) { binding in
Toggle("", isOn: binding)
Divider()
Text(binding.wrappedValue ? "on" : "off")
}
}
}

关于swift - 从 SwiftUI 的 List 中删除列表元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63079221/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com