Search code examples
swiftuicombine

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?


Solution

  • 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.