Reputation: 3045
From the documentation
An AnyCancellable instance automatically calls cancel() when deinitialized.
Yet in the following code
var cancellable: AnyCancellable?
let subject: PassthroughSubject<Int, Never>? = PassthroughSubject<Int, Never>()
cancellable = subject?.sink(receiveValue: {
print("-> sending to cancellable \($0)")
})
print("send 1")
subject?.send(1)
// documentation states "An AnyCancellable instance automatically calls cancel() when deinitialized."
print("cancellable nil'd")
cancellable = nil
print("send 2")
subject?.send(2)
print("send 3")
subject?.send(3)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
print("done")
}
/*
send 1
-> sending to cancellable 1
cancellable nil'd
send 2
-> sending to cancellable 2
send 3
-> sending to cancellable 3
done
*/
Shows that nil'ing cancellable does not stop the subscriber from getting values.
While using a Set and removing all or nil'ing the set will stop the subscriptions. I even tried throwing everything into an autoreleasepool and it didn't do anything. Is the AnyCancellable in the code not getting deinitialized? Is something hanging on to it?
Upvotes: 0
Views: 341
Reputation: 154583
You are testing this in a Playground. The Swift Playgrounds are notorious for hanging on to objects with an extra reference so that you can interact with them in the Playground. This makes the Playground a poor choice for testing the allocation and freeing of objects.
Try this in a real app and you should find that it works as advertised.
Note:
I have found that it will sometimes work out in a Playground if you put all of your code into a function (such as test()
) and then call the function. That prevents variables at top level from being defined and hanging on to object references.
Upvotes: 3