【问题标题】:SwiftUI: ObservedObject/ObservableObject weird behaviorSwiftUI:ObservedObject/ObservableObject 奇怪的行为
【发布时间】:2021-05-07 10:56:32
【问题描述】:

我最近在SwiftUIObservedObject/ObservableObject遇到了以下问题:

如果 ObservedObject/ObservableObject 在视图中发布,则会重新计算 body 属性 - 正如预期的那样。

但是如果body 属性中有一个子视图,它也有一个ObservedObject,那么奇怪的是,视图不仅会重新计算子视图的body 属性,还会重新计算整个object

ObservedObject 的状态当然是lost从子视图中。

当然,您可以通过.environmentObject()ObservableObject 添加到子视图中来防止这种情况发生,但我认为这不是最好的解决方案,尤其是对于更复杂的视图层次结构。

这里是一个示例代码:

struct ContentView: View {
    
    @ObservedObject var contentViewModel: ContentViewModel = ContentViewModel()
    
    var body: some View {
        VStack {
            Button {
                self.contentViewModel.counter += 1
            } label: {
                Text(String(self.contentViewModel.counter))
            }
            
            SubView()
        }
    }
}
class ContentViewModel: ObservableObject {
    @Published var counter: Int = 0
}

以及子视图:

struct SubView: View {
    
    @ObservedObject var subViewModel: SubViewModel = SubViewModel()
    
    
    var body: some View {
        Button {
            self.subViewModel.counter += 1
        } label: {
            Text(String(self.subViewModel.counter))
        }
    }
}
class SubViewModel: ObservableObject {
    @Published var counter: Int = 0
}

这里是示例代码的外观/工作方式:

我意识到的最后一件奇怪的事情,只有当你使用 Observed Object 时才会出现这种情况。如果我将子视图中的@ObservedObject var subViewModel: SubViewModel = SubViewModel() 替换为@State var counter: Int = 0,它将再次正常工作并保留状态。

也许我错过了一些东西,但我真的很困惑。我非常感谢任何答案和解决方案。如果您还有其他问题可以发表评论,我会在 24 小时内回复(只要问题是开放的)。

【问题讨论】:

    标签: swift swiftui observableobject observedobject


    【解决方案1】:

    使用 @StateObject 声明您的 ViewModel。 @StateObject 不会为每次重新渲染的视图重新创建 more

    struct SubView: View {
        @StateObject var subViewModel: SubViewModel = SubViewModel() //<--- Here
        
        var body: some View {
            Button {
                self.subViewModel.counter += 1
            } label: {
                Text(String(self.subViewModel.counter))
            }
        }
    }
    

    【讨论】:

    【解决方案2】:

    我找到了一个完美的解决方案:

    您可以在 iOS 14 (SwiftUI v2.0) 中将 @ObservedObject 替换为 @StateObject (thx @Raja Kishan),或者您可以为 View 创建一个 Wrapper 并模拟 iOS 13 中 @StateObject 的行为 ( SwiftUI v1.0):

    struct SubViewWrapper: View {
        @State var subViewModel: SubViewModel = SubViewModel()
    
        var body: some View {
            SubView(subViewModel: self.subViewModel)
        }
    }
    

    然后在 ContentView 中使用 SubViewWrapper() 而不是 SubView()

    struct ContentView: View {
        
        @ObservedObject var contentViewModel: ContentViewModel = ContentViewModel()
        
        var body: some View {
            VStack {
                Button {
                    self.contentViewModel.counter += 1
                } label: {
                    Text(String(self.contentViewModel.counter))
                }
                
                SubViewWrapper()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2015-07-20
      • 2010-10-03
      • 2021-07-12
      • 2013-10-04
      相关资源
      最近更新 更多