我想延长 Array<T>
基本上返回 Binding<T>
.
这样做的目的是有一种方便的方法来创建 Binding
在 DetailView
这是从 NavigationLink
调用的的 List
.
这是我到目前为止得到的:
extension Array where Element: Identifiable {
mutating func getBinding(of instance: Element) -> Binding<Element> {
if let index = self.firstIndex(where: { $0.id == instance.id }) {
return Binding(
get: { self[index] }, //error
set: { self[index] = $0}) //error
} else {
fatalError() //implement error handling here
}
}
}
我收到错误 Escaping closure captures mutating 'self' parameter
在指定地点。我该如何解决这个问题?
长话短说
以下是我想使用此扩展程序的方式:
class ViewModel: ObservableObject {
@Published var items: [Item]
init(with items: [Item] = [Item]()) {
self.items = items
}
}
struct Item: Identifiable, Hashable {
let id: UUID
var title: String
static var sampleItems: [Item] {
var items = [Item]()
for i in 0..<10 {
items.append(Item(id: UUID(), title: "item \(i)"))
}
return items
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel(with: Item.sampleItems)
var body: some View {
NavigationView {
List {
Section {
ForEach(viewModel.items) { item in
//MARK: Using Array.getBinding(of:) here
NavigationLink(item.title, destination: DetailView(item: viewModel.items.getBinding(of: item)))
}
}
}
}
}
}
struct DetailView: View {
@Binding var item: Item
var body: some View {
TextField("Item Title", text: $item.title)
}
}
最佳答案
将扩展名更改为:
extension Binding {
func getBinding<T>(of instance: T) -> Binding<T>
where Value == [T], T: Identifiable {
if let index = self.wrappedValue.firstIndex(where: { $0.id == instance.id }) {
return .init(
get: { self.wrappedValue[index] }, //error
set: { self.wrappedValue[index] = $0 }) //error
} else {
fatalError() //implement error handling here
}
}
}
现在代替 DetailView(item: viewModel.items.getBinding(of: item))
做 DetailView(item: $viewModel.items.getBinding(of: item))
(注意 $
)
编辑,奖励:
我有一份奖励送给你,希望你会喜欢。这将使过程更好,代码更清晰。请注意,它与您当前的代码在性能方面的差异为 0。
添加此扩展以开始:
extension Binding {
subscript<T>(_ index: Int) -> Binding<T> where Value == [T] {
.init(get: {
self.wrappedValue[index]
},
set: {
self.wrappedValue[index] = $0
})
}
}
并将您的 ForEach
更改为:
ForEach(viewModel.items.indices) { index in
let item = viewModel.items[index]
NavigationLink(item.title, destination: DetailView(item: $viewModel.items[index]))
}
希望你喜欢:)
关于SwiftUI:扩展数组以获得数组实例的绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67059931/