Reputation: 11772
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
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
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