sup*_*cio 56 ios swift swiftui
如果我ObservableObject在 SwiftUI 中有一个,我可以将其称为@ObservedObject:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
Run Code Online (Sandbox Code Playgroud)
或者作为@StateObject:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
Run Code Online (Sandbox Code Playgroud)
但两者之间的实际区别是什么?有没有一种情况比另一种更好,或者它们是两种完全不同的东西?
paw*_*222 73
@观察对象
当视图创建自己的@ObservedObject实例时,每次丢弃和重绘视图时都会重新创建它:
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
}
Run Code Online (Sandbox Code Playgroud)
相反,当视图被重绘时,@State变量将保持其值。
@StateObject
A@StateObject是@ObservedObjectand的组合@State-ViewModel即使在视图被丢弃和重绘后,的实例也会被保留和重用:
struct ContentView: View {
@StateObject var viewModel = ViewModel()
}
Run Code Online (Sandbox Code Playgroud)
表现
尽管@ObservedObject如果视图被迫经常重新创建重量级对象,它会影响性能,但当@ObservedObject它不复杂时,它应该无关紧要。
何时使用@ObservedObject
现在似乎没有理由使用 an @ObservedObject,那么什么时候应该使用它?
对于在使用它的视图中初始化的任何可观察属性,您应该使用 @StateObject。如果 ObservableObject 实例是在外部创建并传递给使用它的视图,则使用 @ObservedObject 标记您的属性。
请注意,可能的用例太多,有时可能需要在您的视图中重新创建一个可观察的属性。在这种情况下,最好使用@ObservedObject.
有用的链接:
sam*_*ize 22
Apple 文档确实解释了为什么用 初始化ObservedObject是不安全的。
SwiftUI 可能随时创建或重新创建视图,因此使用给定的输入集初始化视图始终会产生相同的视图,这一点很重要。因此,在视图中创建观察对象是不安全的。
解决办法是StateObject。
同时,文档向我们展示了我们应该如何在视图(或应用程序/场景)中创建数据模型,当它可以保持真理时,并将其传递给另一个视图。
struct LibraryView: View {
@StateObject var book = Book() // Hold on to the 1 truth
var body: some View {
BookView(book: book) // Pass it to another view
}
}
struct BookView: View {
@ObservedObject var book: Book // From external source
}
Run Code Online (Sandbox Code Playgroud)
Dáv*_*tor 15
尽管pawello2222 的回答很好地解释了视图本身创建其视图模型时的差异,但重要的是要注意将视图模型注入视图时的差异。
当您将视图模型注入视图时,只要视图模型是引用类型,@ObservedObject和之间就没有区别@StateObject,因为将视图模型注入视图的对象也应该持有对视图模型的引用,因此重绘子视图时,视图模型不会被破坏。
class ViewModel: ObservableObject {}
struct ParentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
ChildView(viewModel: viewModel) // You inject the view model into the child view
}
}
// Even if `ChildView` is discarded/redrawn, `ViewModel` is kept in memory, since `ParentView` still holds a reference to it - `ViewModel` is only released and hence destroyed when `ParentView` is destroyed/redrawn.
struct ChildView: View {
@ObservedObject var viewModel: ViewModel
}
Run Code Online (Sandbox Code Playgroud)
这是一个例子。每次单击refresh按钮时,CountViewObserved强制销毁/重新创建 StateObjectClass,因此您可以看到0,这是不期望的。
import SwiftUI
import Combine
class StateObjectClass:ObservableObject{
let type:String
let id:Int
@Published var count = 0
init(type:String){
self.type = type
self.id = Int.random(in: 0...1000)
print("type:\(type) id:\(id) init")
}
deinit {
print("type:\(type) id:\(id) deinit")
}
}
struct CountViewState:View{
@StateObject var state = StateObjectClass(type:"StateObject")
var body: some View{
VStack{
Text("@StateObject count :\(state.count)")
Button("+1"){
state.count += 1
}
}
}
}
struct CountViewObserved:View{
@ObservedObject var state = StateObjectClass(type:"Observed")
var body: some View{
VStack{
Text("@Observed count :\(state.count)")
Button("+1"){
state.count += 1
}
}
}
}
struct ContentView: View {
@State var count = 0
var body: some View {
VStack{
Text("refresh CounterView count :\(count)")
Button("refresh"){
count += 1
}
CountViewState()
.padding()
CountViewObserved()
.padding()
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9285 次 |
| 最近记录: |