I’m asking for educational purposes.
This code is from Apple’s docs
What is the point of updates.cancel()
?
Also why would deinit()
get called as long as there are dangling references to the running Task and back to self?
If await verificationResult in Transaction.updates
would hang (I’m guessing this is some iterator waiting for something to happen which might never happen) I don’t have a clear opportunity to check for .isCancelled
.
Does Apple’s SDK code somehow look at the Task it is running inside periodically and is checking for .isCancelled?
final class TransactionObserver {
var updates: Task<Void, Never>? = nil
init() {
updates = newTransactionListenerTask()
}
deinit {
// Cancel the update handling task when you deinitialize the class.
updates?.cancel()
}
private func newTransactionListenerTask() -> Task<Void, Never> {
Task(priority: .background) {
for await verificationResult in Transaction.updates {
self.handle(updatedTransaction: verificationResult)
}
}
}
// [...]
}
>Solution :
What is the point of updates.cancel()?
Inside of the sequences returned by Transaction.updates
, there is a check for isCancelled
. When the task is cancelled, the AsyncSequence will terminate. Checking for cancellation is a requirement of all AsyncSequences. If you discover that Transaction.updates
does not cancel correctly, that is a bug and you should report it to Apple. See Cancellation in the AsyncIteratorProtocol docs for details.
Also why would deinit() get called as long as there are dangling references to the running Task and back to self?
That does look like a retain loop, and I would open a Feedback to Apple to request that they rework their example.
Does Apple’s SDK code somehow look at the Task it is running inside periodically and is checking for .isCancelled?
Absolutely not. It is the responsibility of the code inside the Task to check for cancellation. In this case, the responsibility of Transaction.updates
.