来自 ObservableObject 的绑定值

use*_*037 36 swift swiftui combine

目的:

我有一个模型,它是一个ObservableObject. 它有一个Bool属性,我想用这个Bool属性来初始化一个@Binding变量。

问题:

  1. 如何将@ObservableObjecta转换为 a @Binding
  2. 创建 a@State是初始化 a 的唯一方法@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)
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 41

Binding 可以通过以下方式创建变量:

  1. @State 变量的投影值提供了一个 Binding<Value>
  2. @ObservedObject变量的投影值提供了一个包装器,您可以从中获取Binding<Subject>它所有属性的
  3. 第 2 点同样适用@EnvironmentObject
  4. 您可以通过为 getter 和 setter 传递闭包来创建一个 Binding 变量,如下所示:
let button = SaleButton(isOn: .init(get: { car.isReadyForSale },
                                    set: { car.isReadyForSale = $0} ))
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 正如@nayem 所指出的,您需要在视图中添加@State/ @ObservedObject/ @EnvironmentObject/ @StateObject(在 SwiftUI 2.0 中添加),以便 SwiftUI 自动检测更改。
  • 使用$前缀可以方便地访问投影值。

  • 我通过 @Asperi 找到了几个与 SwiftUI 相关的有用/需要的答案 - 继续贡献:竖起大拇指: (4认同)

nay*_*yem 15

  1. 您有多种选择来观察ObservableObject. 如果要和对象的状态保持同步,就不可避免地要观察有状态对象的状态。从选项中,最常见的是:

    • @State
    • @ObservedObject
    • @EnvironmentObject

这取决于您,哪一种适合您的用例。

  1. 不可以。但是您需要有一个对象,该对象可以随时观察到对该对象所做的任何更改。

在现实中,你会有这样的事情:

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")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您准备好了,@EnvironmentObject您将使用以下命令初始化您的视图:

let contentView = ContentView().environmentObject(Car())
Run Code Online (Sandbox Code Playgroud)