我正在构建一个结构与Apple tutorial类似的应用。我的应用程序有一个ListView
,它可以导航到DetailsView
。 DetailsView
由UIKit
自定义UIView
组成,我将其与UIViewRepresentable
包装在一起。到目前为止,一切都很好。
现在,我现在有一个在内存中实例化的列表(比方说,地址),最终将被核心数据替换。我可以将@EnvironmentObject
绑定(使用List<Address>
到ListView
。
我遇到的问题是为每个DetailsView
绑定元素。上面引用的Apple教程做了一些我认为不好的事情-由于某种原因(我不知道),它是:
List
绑定到详细信息视图(使用@EnvironmentObject
)landmark
,在我的情况下为address
)传递到详细信息视图List
中搜索元素,以更新列表中的元素。这似乎很昂贵,尤其是如果列表很大。以下是我怀疑的#3的代码:
Button(action: {
self.userData.landmarks[self.landmarkIndex].isFavorite.toggle()
})
在他们的代码中,self.landmarkIndex
进行线性搜索:
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}
我要做的是将元素直接绑定到DetailsView
,并对该元素进行更新以更新列表。到目前为止,我还无法实现这一目标。
有人知道正确的方法吗?看来本教程所指向的方向无法扩展。
答案 0 :(得分:1)
您可以传递Landmark
而不是传递Binding<Landmark>
对象。
LandmarkList.swift:将迭代从userData.landmark
更改为其索引,以便获取绑定。然后将出价传递到LandmarkDetail
和LandmarkRow
struct LandmarkList: View {
@EnvironmentObject private var userData: UserData
var body: some View {
NavigationView {
List {
Toggle(isOn: $userData.showFavoritesOnly) {
Text("Show Favorites Only")
}
ForEach(userData.landmarks.indices) { index in
if !self.userData.showFavoritesOnly || self.userData.landmarks[index].isFavorite {
NavigationLink(
destination: LandmarkDetail(landmark: self.$userData.landmarks[index])
.environmentObject(self.userData)
) {
LandmarkRow(landmark: self.$userData.landmarks[index])
}
}
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}
LandmarkDetail.swift:将landmark
更改为Binding<Landmark>
,然后根据绑定切换收藏夹
@Binding var landmark: Landmark
.
.
.
Button(action: {
self.landmark.isFavorite.toggle()
}) {
if self.landmark
.isFavorite {
Image(systemName: "star.fill")
.foregroundColor(Color.yellow)
} else {
Image(systemName: "star")
.foregroundColor(Color.gray)
}
}
LandmarkRow.swift:将界标更改为Binding
@Binding var landmark: Landmark
答案 1 :(得分:0)
以下是直接对模型Address
项目使用绑定的方法示例
假设有一个类似的视图模型,其中Address
是Identifiable
结构
class AddressViewModel: ObservableObject {
@Published var addresses: [Address] = []
}
因此,在ListView
中的某个地方,您可以使用以下
ForEach (Array(vm.addresses.enumerated()), id: \.element.id) { (i, address) in
NavigationLink("\(address.title)",
destination: DetailsView(address: self.$vm.addresses[i])) // pass binding !!
}