来自 ObservableObject 的绑定值
Binding value from an ObservableObject
目标:
我有一个模型是 ObservableObject
。它有一个 Bool
属性,我想用这个 Bool
属性 来初始化一个 @Binding
变量。
问题:
- 如何将
@ObservableObject
转换为 @Binding
?
- 创建
@State
是初始化 @Binding
的唯一方法吗?
注:
- 我知道我可以使用
@ObservedObject
/ @EnvironmentObject
,我知道它很有用,但我不确定一个简单的按钮是否需要访问整个模型。
- 还是我的理解有误?
代码:
import SwiftUI
import Combine
import SwiftUI
import PlaygroundSupport
class Car : ObservableObject {
@Published var isReadyForSale = true
}
struct SaleButton : View {
@Binding var isOn : Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "On" : "Off")
}
}
}
let car = Car()
//How to convert an ObservableObject to a Binding
//Is creating an ObservedObject or EnvironmentObject the only way to handle a Observable Object ?
let button = SaleButton(isOn: car.isReadyForSale) //Throws a compilation error and rightly so, but how to pass it as a Binding variable ?
PlaygroundPage.current.setLiveView(button)
Binding
变量可以通过以下方式创建:
@State
变量的预测值提供 Binding<Value>
@ObservedObject
变量的投影值提供了一个包装器,您可以从中获取 Binding<Subject>
的所有属性
- 第 2 点也适用于
@EnvironmentObject
。
- 您可以通过为 getter 和 setter 传递闭包来创建绑定变量,如下所示:
let button = SaleButton(isOn: .init(get: { car.isReadyForSale },
set: { car.isReadyForSale = [=10=]} ))
注:
- 正如@nayem 指出的那样,您需要
@State
/ @ObservedObject
/ @EnvironmentObject
/ @StateObject
(在 SwiftUI 2.0 中添加) 在 SwiftUI 的视图中自动检测更改。
- 可以使用
$
前缀方便地访问投影值。
struct ContentView: View {
@EnvironmentObject var car: Car
var body: some View {
SaleButton(isOn: self.$car.isReadyForSale)
}
}
class Car: ObservableObject {
@Published var isReadyForSale = true
}
struct SaleButton: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "On" : "Off")
}
}
}
确保您的 SceneDelegate
中包含以下内容:
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
.environmentObject(Car())
您有多种选择来观察ObservableObject
。如果要与对象的状态同步,那么观察stateful对象的状态是免不了的。从选项中,最常见的是:
@State
@ObservedObject
@EnvironmentObject
这取决于您,哪一个适合您的用例。
- 没有。但是你需要有一个对象,可以观察到在任何时间点对该对象所做的任何更改。
在现实中,你会遇到这样的事情:
class Car: ObservableObject {
@Published var isReadyForSale = true
}
struct ContentView: View {
// It's upto you whether you want to have other type
// such as @State or @ObservedObject
@EnvironmentObject var car: Car
var body: some View {
SaleButton(isOn: $car.isReadyForSale)
}
}
struct SaleButton: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "Off" : "On")
}
}
}
如果您准备好 @EnvironmentObject
,您将初始化您的视图:
let contentView = ContentView().environmentObject(Car())
在我的例子中,我使用 .constant(viewModel)
将 viewModel 传递给 ListView @Binding var viewModel
示例
struct CoursesView: View {
@StateObject var viewModel = CoursesViewModel()
var body: some View {
ZStack {
ListView(viewModel: .constant(viewModel))
ProgressView().opacity(viewModel.isShowing)
}
}
}
struct ListView: View {
@Binding var viewModel: CoursesViewModel
var body: some View {
List {
ForEach(viewModel.courses, id: \.id) { course in
Text(couse.imageUrl)
}
}
}
}
目标:
我有一个模型是 ObservableObject
。它有一个 Bool
属性,我想用这个 Bool
属性 来初始化一个 @Binding
变量。
问题:
- 如何将
@ObservableObject
转换为@Binding
? - 创建
@State
是初始化@Binding
的唯一方法吗?
注:
- 我知道我可以使用
@ObservedObject
/@EnvironmentObject
,我知道它很有用,但我不确定一个简单的按钮是否需要访问整个模型。 - 还是我的理解有误?
代码:
import SwiftUI
import Combine
import SwiftUI
import PlaygroundSupport
class Car : ObservableObject {
@Published var isReadyForSale = true
}
struct SaleButton : View {
@Binding var isOn : Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "On" : "Off")
}
}
}
let car = Car()
//How to convert an ObservableObject to a Binding
//Is creating an ObservedObject or EnvironmentObject the only way to handle a Observable Object ?
let button = SaleButton(isOn: car.isReadyForSale) //Throws a compilation error and rightly so, but how to pass it as a Binding variable ?
PlaygroundPage.current.setLiveView(button)
Binding
变量可以通过以下方式创建:
@State
变量的预测值提供Binding<Value>
@ObservedObject
变量的投影值提供了一个包装器,您可以从中获取Binding<Subject>
的所有属性- 第 2 点也适用于
@EnvironmentObject
。 - 您可以通过为 getter 和 setter 传递闭包来创建绑定变量,如下所示:
let button = SaleButton(isOn: .init(get: { car.isReadyForSale },
set: { car.isReadyForSale = [=10=]} ))
注:
- 正如@nayem 指出的那样,您需要
@State
/@ObservedObject
/@EnvironmentObject
/@StateObject
(在 SwiftUI 2.0 中添加) 在 SwiftUI 的视图中自动检测更改。 - 可以使用
$
前缀方便地访问投影值。
struct ContentView: View {
@EnvironmentObject var car: Car
var body: some View {
SaleButton(isOn: self.$car.isReadyForSale)
}
}
class Car: ObservableObject {
@Published var isReadyForSale = true
}
struct SaleButton: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "On" : "Off")
}
}
}
确保您的 SceneDelegate
中包含以下内容:
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
.environmentObject(Car())
您有多种选择来观察
ObservableObject
。如果要与对象的状态同步,那么观察stateful对象的状态是免不了的。从选项中,最常见的是:@State
@ObservedObject
@EnvironmentObject
这取决于您,哪一个适合您的用例。
- 没有。但是你需要有一个对象,可以观察到在任何时间点对该对象所做的任何更改。
在现实中,你会遇到这样的事情:
class Car: ObservableObject {
@Published var isReadyForSale = true
}
struct ContentView: View {
// It's upto you whether you want to have other type
// such as @State or @ObservedObject
@EnvironmentObject var car: Car
var body: some View {
SaleButton(isOn: $car.isReadyForSale)
}
}
struct SaleButton: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "Off" : "On")
}
}
}
如果您准备好 @EnvironmentObject
,您将初始化您的视图:
let contentView = ContentView().environmentObject(Car())
在我的例子中,我使用 .constant(viewModel)
将 viewModel 传递给 ListView @Binding var viewModel
示例
struct CoursesView: View {
@StateObject var viewModel = CoursesViewModel()
var body: some View {
ZStack {
ListView(viewModel: .constant(viewModel))
ProgressView().opacity(viewModel.isShowing)
}
}
}
struct ListView: View {
@Binding var viewModel: CoursesViewModel
var body: some View {
List {
ForEach(viewModel.courses, id: \.id) { course in
Text(couse.imageUrl)
}
}
}
}