微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI:ObservedObject/ObservableObject 奇怪的行为

如何解决SwiftUI:ObservedObject/ObservableObject 奇怪的行为

我最近在使用 SwiftUI/ObservedobjectObservableObject 中遇到了以下问题:

如果 Observedobject/ObservableObject 在视图中发布,body 属性会按预期重新计算。

但是如果在 body 属性中有一个子 View 也有一个 Observedobject,那么奇怪的是,这个 View 不仅重新计算了子 View 的 body 属性,而且整个object

状态 Observedobject 当然是从子视图中丢失

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

这是一个示例代码

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
}

这里是示例代码的外观/工作原理:

Preview

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

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

解决方法

使用 @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))
        }
    }
}
,

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

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

@StateObject

然后在 ContentView 中使用 struct SubViewWrapper: View { @State var subViewModel: SubViewModel = SubViewModel() var body: some View { SubView(subViewModel: self.subViewModel) } } 而不是 SubViewWrapper()

SubView()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。