SwiftUI ObservedObject 不更新父视图

Posted

技术标签:

【中文标题】SwiftUI ObservedObject 不更新父视图【英文标题】:SwiftUI ObservedObject not updating parent view 【发布时间】:2021-07-21 10:14:43 【问题描述】:

我有 2 个模型:BagFood。一个袋子包含 1 个食物。食物有名字。

我正在尝试将 Food.name 属性与父视图 (BagView) 中显示的 TextField 和子视图中显示的另一个 TextField (食物视图)。

当我编辑父级的文本字段时,更改会显示在机器人视图中。 当我编辑子文本字段时,更改显示在父视图中。为什么?

这是我的示例代码:

class Bag: ObservableObject 
    @Published var food: Food
    
    init(food: Food) 
        self.food = food
    


class Food: ObservableObject 
    @Published var name: String
    
    init(name: String) 
        self.name = name
    


struct BagView: View 
    @ObservedObject var bag: Bag
    
    var body: some View 
        VStack 
            TextField("Placeholder 1", text: $bag.food.name)
            FoodView(food: bag.food)
        
    


struct FoodView: View 
    @ObservedObject var food: Food
    
    var body: some View 
        TextField("Placeholder 2", text: $food.name)
    

【问题讨论】:

【参考方案1】:

要在两个视图之间传递数据,您需要将Binding 用于FoodView

struct BagView: View 
    @ObservedObject var bag: Bag

    var body: some View 
        VStack 
            TextField("Placeholder 1", text: $bag.food.name)
            FoodView(food: $bag.food)
        
    


struct FoodView: View 
    @Binding var food: Food
    
    var body: some View 
        TextField("Placeholder 2", text: $food.name)
    

回答您的评论,我建议添加一个额外的视图/包装器来预览Binding

附:顺便说一句,如果您打算将Food 用作Bag 视图模型的一部分,则无需使用已发布属性使其类。结构就够了。

struct Food 
    var name: String

【讨论】:

谢谢。我注意到对 Food 使用 struct 而不是 class 的唯一缺点是编辑器预览不适用于 FoodView:例如,如果我将 2 个 TextField 与 $food.name 放在一起,它们不会保持同步。 可能您使用“常量”来预览绑定。尝试实现一个 View Wrapper。我在答案中添加了代码。

以上是关于SwiftUI ObservedObject 不更新父视图的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 尽管使用了 @Published 和 @ObservedObject,但视图不会更新

SwiftUI:如何在 Pageable 中访问 ObservedObject?

SwiftUI - ObservedObject 永远不会被释放

SwiftUI:@ObservedObject 与 @StateObject 子视图性能?

SwiftUI - 如何基于@ObservedObject 为每个列表视图项创建编辑视图

当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive