filimo
(VictorK)
1
I noticed that 'sink' never was called when using 'receive' . I tested on Xcode 11 beta 5.
public enum SomeError: Error {
case someError
}
Just("1")
.tryMap { val -> String in
if Bool.random() { throw SomeError.someError }
return val
}
.flatMap { val -> Empty<String, Error> in
return .init()
}
.receive(on: RunLoop.main)
.sink(receiveCompletion: { completion in
print(1, completion)
switch completion {
case .failure(let error):
print(3, error)
case .finished:
break
}
}) { val in
print(2, val)
}
mayoff
(Rob Mayoff)
2
The sink modifier returns an AnyCancellable. When the AnyCancellable is destroyed, it cancels the subscription. In your example, you're not storing the AnyCancellable, so it is destroyed immediately, cancelling the subscription immediately.
filimo
(VictorK)
3
I've changed my code like this let requestCancellable = Just("1") but 'sink' isn't invoked.
When I remove .receive(on: RunLoop.main) then 'sink' start to be invoked.
1 Like
filimo
(VictorK)
4
If I remove 'flatMap' or 'receive' then 'sink' is started to invoke. I can't understand how it relative to AnyCancelable. I've written a simple code to test it.
let requestCancellable = Just("1")
.flatMap { val -> Empty<String, Never> in
return .init()
}
.receive(on: RunLoop.main)
.sink(receiveCompletion: { completion in
print(1, completion)
}) { val in
print(2, val)
}
Jon_Shier
(Jon Shier)
5
It's entirely possible that by shortening the pipeline, you're winning the race between the deinitialization of your AnyCancellable and sink being called. Have you ensured its lifetime is properly managed?
filimo
(VictorK)
7
I save requestCancellable in my store object and my view uses this store.
filimo
(VictorK)
8
sink is never invoked.
struct MainView : View {
var requestCancellable: AnyCancellable
init() {
requestCancellable = Just("1")
.flatMap { val -> Empty<String, Never> in
return .init()
}
.receive(on: RunLoop.main)
.sink(receiveCompletion: { completion in
print(1, completion)
}) { val in
print(2, val)
} }
var body: some View {
VStack {
EmptyView()
}
}
}
mayoff
(Rob Mayoff)
9
I reproduced the problem in a playground using Xcode 11b5 on macOS 10.14.6. I think it's a Combine framework bug.
How do you manage the lifetime other than storing a reference to the AnyCancellable?
hbk3
11
I also was able to reproduce this with xCode Version 12.1 (12A7403)
publisher
// any of this
.receive(on: DispatchQueue.main)
.receive(on: RunLoop.main)
.sink(receiveValue: updateState(_:))
.store(in: &subscribers)
and updateState never called
That's correct, when I remove .receive method it actually calls the sink() part.