@Observable
@Observable
在 WWDC23 上发布,旨在简化观察相关代码并提高应用程序的性能。
性能提升来自于这样一个事实:SwiftUI 开始跟踪 SwiftUI 视图主体中使用了哪些属性,只有当跟踪的属性发生更改时才会触发视图渲染。如果同一模型对象中的任何其他属性发生变化,则不会发生新的重新渲染 - 非常好。
利用@Observable
和@Bindable
来替代以前的ObservableObject、@Published
、@StateObject
的写法,主要区别在于我们可以放弃使用 @Published 属性包装器,而不是遵守 ObservableObject 协议,而是在视图模型定义前面添加 @Observable 。
符合 ObservableObject 写法:
swift
class ContentViewModel: ObservableObject {
@Published var username: String = ""
}
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
var body: some View {
VStack {
TextField("Username", text: $viewModel.username)
}
}
}
@Observable 写法:
swift
@Observable
class Content2ViewModel {
var username: String = ""
}
struct ContentView2: View {
@Bindable private var viewModel = Content2ViewModel()
var body: some View {
VStack {
TextField("Username", text: $viewModel.username)
}
}
}
@Bindable
@Bindable
包装器是为了解决这种情况而创建的,它允许您创建到对象属性的绑定,用于创建与带@Observable
注释的模型上的属性的绑定。如果不使用@Bindable
就不能与@Observable
的模型的进行绑定。
swift
@Observable
class SearchModel {
var query: String = ""
var results: [SearchResult] = []
// ...
}
struct SearchView {
let searchModel: SearchModel
var body: some View {
// Cannot find '$searchModel' in scope
TextField("Search query", text: $searchModel.query)
}
}
我们无法绑定到一个普通的 SearchModel
的属性,我们需要某种机制来实现这一点,我们可以使用以下的方式:
-
是使用上一篇文章提到的
Binding
,创建Binding
实例并传递一个get
和set
闭包。 -
@Bindable
属性包装器:
swift
struct SearchView {
@Bindable var searchModel: SearchModel
var body: some View {
// This works
TextField("Search query", text: $searchModel.query)
}
}
@Bindable
可以从属性包装器获取投影值,并且投影值提供我们的绑定。换句话说,我们现在可以对模型的query
属性绑定。
less
struct SearchView {
@Environment(.searchModel) var searchModel
var body: some View {
@Bindable var bindableSearchModel = searchModel
// This works
TextField("Search query", text: $bindableSearchModel.query)
}
}
使用此技术,您可以从环境中提取搜索模型作为不可绑定的属性。为了使其可绑定,您可以在主体内部创建一个标记为 的影子属性@Bindable
。
@Bindable
注意事项:
- 您正在包装一个带有注释的类
@Observed
- 您需要提供另一个视图来绑定到模型对象上的属性
请注意: 您永远不会在
@Binding
和@Bindable
之间进行选择。@Binding
属性包装器表明视图上的某些状态由父视图拥有,并且您对基础数据具有读写访问权限。@Bindable
表示用于创建与符合Observable协议的数据模型对象的可变属性的绑定。