In the following code "Test" should be printed in the console when the Button is pressed, but it's not. The event is not send through the publisher. Any idea what happened with PassthroughSubject in Xcode 11 Beta 5 ? (in Xcode 11 Beta 4 it works well)
var body: some View {
let publisher = PassthroughSubject<String, Never>()
publisher.sink { (str) in
print(str)
}
return Button("OK") {
publisher.send("Test")
}
}
P.S. I know there are other ways to print a string when a button is pressed, I just wanna show a simple send-receive example
.sink()
returns an AnyCancellable
object. You should never ignored it. Never do this:
// never do this!
publisher.sink { ... }
// never do this!
let _ = publisher.sink { ... }
And if you assign it to a variable, make sure it is not short lived. As soon as the cancellable object gets deallocated, the subscription will get cancelled too.
// if cancellable is deallocated, the subscription will get cancelled
let cancellable = publisher.sink { ... }
Since you asked to use sink
inside a view, I'll post a way of doing it. However, inside a view, you should probably use .onReceive()
instead. It is way more simple.
Using sink:
When using it inside a view, you need to use a @State
variable, to make sure it survives after the view body was generated.
The DispatchQueue.main.async
is required, to avoid the state being modified while the view updates. You would get a runtime error if you didn't.
struct ContentView: View {
@State var cancellable: AnyCancellable? = nil
var body: some View {
let publisher = PassthroughSubject<String, Never>()
DispatchQueue.main.async {
self.cancellable = publisher.sink { (str) in
print(str)
}
}
return Button("OK") {
publisher.send("Test")
}
}
}
Using .onReceive()
struct ContentView: View {
var body: some View {
let publisher = PassthroughSubject<String, Never>()
return Button("OK") {
publisher.send("Test")
}
.onReceive(publisher) { str in
print(str)
}
}
}
You are missing .store when you subscribe to the sink. You can use .onReceive, but your code is not receiving values because you need to add .store(in: &subscription)
var body: some View {
var subscription = Set<AnyCancellable>()
let publisher = PassthroughSubject<String, Never>()
publisher.sink { (str) in
print(str)
}.store(in: &subscription)
return Button("OK") {
publisher.send("Test")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With