swift 当你可以使用@StateObject时,为什么要使用@ObservableObject?

xdnvmnnf  于 2023-11-16  发布在  Swift
关注(0)|答案(4)|浏览(134)

我一直在学习swiftUI和@StateObject@ObservedObject,并认为我掌握了它,直到我意识到我可以将@ObservedObject@StateObject交换,而不会对代码行为产生任何影响。考虑这个例子:

class SharedModel: ObservableObject {
    @Published var value: String = "Initial Value"
}

struct ContentView: View {
    @StateObject var sharedModel = SharedModel()

    var body: some View {
        VStack {
            Text("Value in ContentView: \(sharedModel.value)")
            TextField("ContentView textfield", text: $sharedModel.value)

            SubView(sharedModel: sharedModel)
        }
    }
}

struct SubView: View {
    @ObservedObject var sharedModel: SharedModel

    var body: some View {
        VStack {
            Text("Value in SubView: \(sharedModel.value)")
            
            TextField("sub textfield", text: $sharedModel.value)
        }
    }
}

字符串
TextField中写入内容将更新两个Text视图中的文本。因此,当SharedModel的属性更新时,ContentView和SubView将更新。很好。但后来我玩了一下,将@ObservedObject更改为@StateObject,并没有注意到任何差异。它和以前一样工作。我认为它的工作方式是,如果属性用@StateObject则它是真实的来源,不会将更改中继到其他@StateObject属性。
那么这里的问题是什么呢?@ObservedObject的意义是什么?如果@StateObject同样可以正常工作,我为什么要使用它?

cedebl8k

cedebl8k1#

StateObject的主要区别是它在SwiftUI中有存储空间,当View重新加载时,它可以保留一个对象。
您可能没有注意到任何差异,但使用ObservedObject进行初始化将导致泄漏,不一致的行为和不必要的数据丢失。
SwiftUI可能随时创建或重新创建视图,因此使用给定的输入集初始化视图总是会导致相同的视图,这一点很重要。因此,在视图中创建观察对象是不安全的。相反,SwiftUI提供了StateObject属性 Package 器,该 Package 器为您存储在视图层次结构中的引用类型创建单个真实值源。
https://developer.apple.com/documentation/swiftui/monitoring-model-data-changes-in-your-app
当从StateObjectStateObject时,你不会得到一个新的对象,因为它是一个class是一个引用类型,它们都指向同一个地址。你需要一个“深”副本,让它们完全不同。
你会有两个不同的o next试图在SwiftUI中拥有相同的东西,所以你可能最终会泄漏。
新的Observable可以做你所描述的,如果你传递一个Observable到一个State SwiftUI现在为你创建一个深副本。

qlfbtfca

qlfbtfca2#

你说的是三件不同的事情:

  • @ObservedObject是一个属性 Package 器,用于-类似于值类型@Binding-不属于当前视图的引用类型对象。在SwiftUI的第一个版本中,它也是当前视图拥有的对象的属性 Package 器。
  • @StateObject是一个属性 Package 器,与值类型@State类似,专门用于当前视图所拥有的引用类型对象。在SwiftUI的后续版本中,它已经取代了@ObservedObject用于 owned 类型。出于兼容性原因,@ObservedObject仍然可以工作,但不推荐使用。
  • 另一方面,ObservableObject是一个协议,并且是使用@StateObject Package 器创建的类所必需的。每当其@Published属性发生更改时,它就会刷新受影响的视图。

请注意ObservableObject@ObservedObject之间的区别。

irlmq6kh

irlmq6kh3#

在SwiftUI的第一个版本中,我们只有@ObservedObject,其中对象由其他对象拥有,例如由单例拥有,在@Published数组中存储所有模型结构并负责加载和保存。然后在第二个版本中添加了@StateObject,它提供了View拥有对象的能力,并在屏幕出现时初始化,当它消失时de-init,即将其用于通过合并管道加载的MVC视图数据。由于现在我们可以使用支持MVC/await的.task来管理与视图数据相关的MVC工作的生命周期,因此我们不再需要@StateObject
对于非JavaScript视图数据,我们使用@State(可以将相关的变量分组在结构中),let@Binding var,并避免使用像您的示例代码中那样会减慢SwiftUI的重量级对象。

xyhw6mcr

xyhw6mcr4#

@ObservableObject:

@ObservableObject is used to declare and inject an observable object into a view. An observable object is a class that conforms to the ObservableObject protocol. It allows you to create an object whose properties can be observed for changes, and when these properties change, the associated view is updated. You use @ObservableObject when you want to inject an external observable object into a view, typically when you're sharing the same instance of the observable object among multiple views.

class UserData: ObservableObject {
@Published var username: String = "User"

字符串
}
struct ContentView:View { @ObservedObject var userData:UserData = UserData()

var body: some View {
    // Use userData properties in the view
}


}
@StateObject:

@StateObject is used for managing the lifecycle of an observable object within a view. It's specifically designed for creating and managing the lifecycle of an observable object within a view. When you use @StateObject, SwiftUI manages the lifecycle of the associated object, ensuring it persists for the duration of the view's existence. It's primarily used when the view itself is responsible for creating and owning the observable object, and the object should be recreated only when the view is re-initialized (e.g., due to the view being reconstructed after a state change).
class UserData: ObservableObject {
@Published var username: String = "User"


}
struct ContentView:View { @StateObject var userData:UserData = UserData()

var body: some View {
    // Use userData properties in the view
}}


总之,@ObservableObject用于将外部可观察对象注入到视图中,而@StateObject用于管理在视图中创建的可观察对象的生命周期。根据对象是由视图本身创建和拥有还是由多个视图共享来选择适当的属性 Package 器是至关重要的。

相关问题