ObservableObject中的@Published属性和普通AnyPublisher属性之间有什么区别

时间:2020-03-06 09:19:57

标签: swiftui combine

我考虑有什么区别

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/xxx/TestApp.app> (loaded)' with name 'MyViewController''

我知道首先可以直接在SwiftUI View中使用它,即使用$符号创建绑定,然后例如使用@Published var isLoggedIn: Bool = false var isLoggedIn: AnyPublisher<Bool, Never>

但是如何使用if $isLoggedIn.animation()达到相同的效果,看来我需要在某个地方调用分配接收器 store()< / strong>。使它工作。因此,像AnyPublisher<Bool, Never>

在SwiftUI中从绑定创建绑定似乎是不可能的

@Published的局限性是我无法进行自定义观察。例如,我可以通过UserDefaults.publisher中的AnyPublisher进行操作。

现在看来我需要同时拥有if $isLoggedIn.animation和更新AnyPublisher

但是我一直认为@Published是常规的AnyPublisher之下的属性包装器,所以为什么不能直接从AnyPublisher在SwiftUI视图中进行绑定?

2 个答案:

答案 0 :(得分:4)

Combine的@Published是由属性包装器包装的发布者。这为它提供了$前缀的属性以及SwiftUI赖以工作的其他功能。

@Published属性也根本不像AnyPublisher@Published始终以Never作为其失败类型,AnyPublisher可以有其他失败案例。

@Published具有状态感/当前值,AnyPublisher则不然。 CurrentValueSubject会最接近,但不会起作用,因为@Published可用作CurrentValueSubject不可能的绑定。一个重要的区别是SwiftUI可以直接为@Published属性分配新值(isLoggedIn = true会在此处触发更改)。

要在SwiftUI中与发布商合作,您需要将其值分配给您在原始问题中提到的专用@Published属性。

答案 1 :(得分:0)

自定义观察的示例用法

import SwiftUI
import Combine

class Model: ObservableObject {
    @Published var flag = false
}


struct ContentView: View {
    @ObservedObject var model: Model
    let handle: AnyCancellable?
    init() {
        let m = Model()
        handle = m.$flag.sink(receiveValue: { (b) in
            print("model flag changed to:", b)
        })
        model = m
    }
    var body: some View {
        Toggle(isOn: $model.flag) {
            Text("Toggle")
        }.padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

来自SwiftUI。查看发布者的方式为

$model.$flag

如果需要。