Michał Ziobro
Michał Ziobro

Reputation: 11772

What is the difference between @Published and normal AnyPublisher property in ObservableObject

I consider what is the difference

@Published var isLoggedIn: Bool = false 

var isLoggedIn: AnyPublisher<Bool, Never> 

I know in the case of first I can use it directly in SwiftUI View i.e. create binding with $ sign and then for example use if $isLoggedIn.animation()

But how can I achieve the same with AnyPublisher<Bool, Never> it seems that there I need to call somewhere assign or sink and store(). To make it work. So creating binding from it in SwiftUI seems to be impossible like if $isLoggedIn.animation

Limitation of @Published is that I cannot make there custom observing. for example UserDefaults which I can do via AnyPublisher from UserDefaults.publisher.

As now it seems I need to have both and make AnyPublisher update @Published var

But I've thought that @Published is property wrapper that has underneath regular AnyPublisher so why I cannot make binding in SwiftUI view directly from AnyPublisher?

Upvotes: 2

Views: 4009

Answers (2)

donnywals
donnywals

Reputation: 7591

Combine's @Published is a publisher that's wrapped by a property wrapper. This gives it the $ prefixed property and other features that SwiftUI relies on to work.

An @Published property is also not like an AnyPublisher at all. @Published always has Never as its failure type, AnyPublisher can have other failure cases.

@Published has a sense of state/ a current value which isn't the case for AnyPublisher. A CurrentValueSubject would come closest but that wouldn't work because @Published can be used as a binding which isn't possible for CurrentValueSubject. An important difference is that SwiftUI can assign new values to an @Published property directly (isLoggedIn = true would trigger a change here).

To work with your publishers in SwiftUI you'll need to assign their values to a dedicated @Published property as you mentioned in your original question.

Upvotes: 7

user3441734
user3441734

Reputation: 17544

example usage of custom observing

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()
    }
}

from SwiftUI.View the publisher is accessible as

$model.$flag

if needed.

Upvotes: 0

Related Questions