SwiftUI中如何绑定集合内元素,同步修改原数组?
解决方案
根据你的需求,有两种常用方式可以实现修改水果后自动同步到Merchant的数组中,不用手动调用更新方法:
场景1:将Fruit改为引用类型(Class)
和你Objective-C中的逻辑完全一致,把Fruit从struct改成class,利用引用类型的特性直接同步修改:
首先定义Fruit和Merchant:
class Fruit: ObservableObject { @Published var name: String init(name: String) { self.name = name } } class Merchant: ObservableObject { @Published var fruits: [Fruit] = [] init() { let apple = Fruit(name: "Apple") let orange = Fruit(name: "Orange") let pear = Fruit(name: "Pear") fruits = [apple, orange, pear] } }
然后修改详情视图,直接传递Fruit实例即可:
struct FruitDetailView: View { var item: Fruit // 引用类型,传递的是对象引用 var body: some View { VStack { Text(item.name) Button("Press Me") { item.name = "Watermelon" // 无需调用merchant的更新方法,修改会自动同步到merchant的fruits数组 } } } }
这种方式下,Merchant数组里存储的是Fruit对象的引用,修改详情页中的item属性时,本质是修改同一个对象的属性,所以Merchant的数组会自动同步变化。
场景2:保持Fruit为值类型(Struct)
如果不想改变Fruit的类型,使用@Binding实现双向绑定:
在列表视图中,通过绑定传递数组中的元素:
struct FruitListView: View { @EnvironmentObject var merchant: Merchant var body: some View { List($merchant.fruits) { $fruit in NavigationLink(destination: FruitDetailView(item: $fruit)) { Text(fruit.name) } } } }
详情视图接收@Binding类型的参数:
struct FruitDetailView: View { @Binding var item: Fruit var body: some View { VStack { Text(item.name) Button("Press Me") { item.name = "Watermelon" // Binding会自动将修改同步回merchant的fruits数组 } } } }
这里的@Binding直接关联了Merchant数组中的具体元素,修改item时会自动更新原数组里的值,无需手动调用同步方法。
原代码需要手动同步的原因
你原来用@State var item: Fruit时,如果Fruit是值类型,传递的是原数据的副本,修改副本不会影响Merchant数组里的原数据,所以必须手动调用updateFruits来替换数组元素。上面两种方式都从根源上避免了这个问题。
内容的提问来源于stack exchange,提问作者bobby123uk
相关产品推荐
相关产品推荐

