@Observable

@ObservableWWDC23 上发布,旨在简化调查相关代码并进步应用程序的功能。

功能提高来自于这样一个事实:SwiftUI 开始盯梢 SwiftUI 视图主体中运用了哪些特点,只有当盯梢的特点产生更改时才会触发视图渲染。假如同一模型目标中的任何其他特点产生变化,则不会产生新的从头渲染 – 非常好。

利用@Observable@Bindable来代替曾经的ObservableObject、@Published@StateObject的写法,主要区别在于咱们能够放弃运用 @Published 特点包装器,而不是恪守 ObservableObject 协议,而是在视图模型界说前面添加 @Observable 。

契合 ObservableObject 写法:

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 写法:

@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的模型的进行绑定。

@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的特点,咱们需求某种机制来完成这一点,咱们能够运用以下的方式:

  1. 是运用上一篇文章提到的Binding,创立Binding实例并传递一个getset闭包

  2. @Bindable特点包装器:

struct SearchView {
  @Bindable var searchModel: SearchModel
  var body: some View {
    // This works
    TextField("Search query", text: $searchModel.query)
  }
}

@Bindable能够从特点包装器获取投影值,而且投影值供给咱们的绑定。换句话说,咱们现在能够对模型的query特点绑定。

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协议的数据模型目标的可变特点的绑定。