@State vs @ObservableObject - 哪个和什么时候?
@State vs @ObservableObject - which and when?
我目前正在熟悉 SwiftUI 和 Combine 框架。我并没有真正理解这两种方法之间的区别。当我们必须跟踪一些数据(比如任务列表)时,我们可以声明一个@State 变量,它的变化会自动发送通知并更新当前视图。但是,看起来也可以这样做:
class TaskList: ObservableObject{
//a list that's going to be modified and updated on different occasions
@Published var list: [String]
}
class TodoListView {
@ObservedObject var todoList = TaskList()
}
所以,我漏掉了一点 - @State 和 @ObservedObject 的方法有何不同,在什么情况下哪个更可取?
谢谢!
主要区别在于 @State
用于结构,而 @ObservedObject
用于 类。 @State
和 @ObservedObject
都实现了类似的目的,即在发生变化时通知您。
A struct
在某些 属性 发生突变时发生变化,这意味着它会重新创建,因此 @State
会更新。当 属性 发生变化时,class
会更新 @ObservedObject
- 使用 @Published
来监听变化。当更新 @State
或 @ObservedObject
时,将重新制作视图主体。
你在这里真正问的问题是 when to use a struct vs a class 在某些情况下是否可行。
在你的例子中,因为 TaskList
只是一个基本的数据结构,不需要很多你想阻止更新视图的属性(通过 using/not 使用 @Published
),你应该使用 struct
和 @State
来代替。
如果您在 SwiftUI View
中将任何变量标记为 @State
并将它们绑定到 View
的 body
内的 属性,则body
将在 @State
变量更改时重新计算,因此您的整个 View
将被重新绘制。此外,@State
变量应作为 View
的唯一真实来源。由于这些原因,@State
变量只能从 View
的 body
中访问和更新,因此应该声明为 private
.
当您绑定某些用户输入时(例如 TextField
的值或从 Picker
中选择的值),您应该使用 @State
。 @State
应该用于 值类型 (struct
s 和 enum
s)。
另一方面,@ObservedObject
应该用于引用类型(class
es),因为只要 @Published
属性 ObservableObject
变化。
当您有一些数据来自 View
外部时,例如在带有 SwiftUI 的 MVVM 架构中,您应该使用 @ObservedObject
,您的 ViewModel
应该存储为 @ObservedObject
在你的 View
.
@ObservedObject
s 的一个常见错误是在 View
本身内部声明和初始化它们。这将导致问题,因为每次 @ObservedObject
发出更新(其 @Published
属性之一被更新)时,将重新创建视图 - 这也会创建一个新的 @ObservedObject
,因为它是在 View
本身中初始化的。为避免此问题,无论何时使用 @ObservedObject
,您总是 必须将其注入视图 。 iOS 14 @StateObject
解决了这个问题。
我目前正在熟悉 SwiftUI 和 Combine 框架。我并没有真正理解这两种方法之间的区别。当我们必须跟踪一些数据(比如任务列表)时,我们可以声明一个@State 变量,它的变化会自动发送通知并更新当前视图。但是,看起来也可以这样做:
class TaskList: ObservableObject{
//a list that's going to be modified and updated on different occasions
@Published var list: [String]
}
class TodoListView {
@ObservedObject var todoList = TaskList()
}
所以,我漏掉了一点 - @State 和 @ObservedObject 的方法有何不同,在什么情况下哪个更可取?
谢谢!
主要区别在于 @State
用于结构,而 @ObservedObject
用于 类。 @State
和 @ObservedObject
都实现了类似的目的,即在发生变化时通知您。
A struct
在某些 属性 发生突变时发生变化,这意味着它会重新创建,因此 @State
会更新。当 属性 发生变化时,class
会更新 @ObservedObject
- 使用 @Published
来监听变化。当更新 @State
或 @ObservedObject
时,将重新制作视图主体。
你在这里真正问的问题是 when to use a struct vs a class 在某些情况下是否可行。
在你的例子中,因为 TaskList
只是一个基本的数据结构,不需要很多你想阻止更新视图的属性(通过 using/not 使用 @Published
),你应该使用 struct
和 @State
来代替。
如果您在 SwiftUI View
中将任何变量标记为 @State
并将它们绑定到 View
的 body
内的 属性,则body
将在 @State
变量更改时重新计算,因此您的整个 View
将被重新绘制。此外,@State
变量应作为 View
的唯一真实来源。由于这些原因,@State
变量只能从 View
的 body
中访问和更新,因此应该声明为 private
.
当您绑定某些用户输入时(例如 TextField
的值或从 Picker
中选择的值),您应该使用 @State
。 @State
应该用于 值类型 (struct
s 和 enum
s)。
另一方面,@ObservedObject
应该用于引用类型(class
es),因为只要 @Published
属性 ObservableObject
变化。
当您有一些数据来自 View
外部时,例如在带有 SwiftUI 的 MVVM 架构中,您应该使用 @ObservedObject
,您的 ViewModel
应该存储为 @ObservedObject
在你的 View
.
@ObservedObject
s 的一个常见错误是在 View
本身内部声明和初始化它们。这将导致问题,因为每次 @ObservedObject
发出更新(其 @Published
属性之一被更新)时,将重新创建视图 - 这也会创建一个新的 @ObservedObject
,因为它是在 View
本身中初始化的。为避免此问题,无论何时使用 @ObservedObject
,您总是 必须将其注入视图 。 iOS 14 @StateObject
解决了这个问题。