I want to quit "DispatchQueue.main.asyncAfter" when deinit is called.
subView.swift
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
self.doSomething()
}
func doSomething(){
if self.subView.flgA == false { //error because subView's deinit is already called
//...
}
}
When ViewController do _ = self.navigationController?.popViewController(animated: true)
and deinit is called, deinit in ViewController and subView is called at first and after a few minutes doSomething()
is called.
I want to stop doSomething()
when popViewController is executed.
How can I do it?
You could schedule a Timer
with this code block
let timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] timer in
self?.doSomething()
}
hold on to the timer and cancel it before popViewController
like this:
timer.invalidate()
Notice the [weak self]
and the self?.domeSomething()
which I put there to avoid the hard reference to the viewcontroller and read Laffen's more detailed answer on this.
In Swift we have something called ARC(Automatic Reference Counting). ARC will make sure any object with at least one strong reference to it, will not be removed from memory.
In your case you're creating a strong reference to self
in the closure of the async task created by DispatchQueue.main.asyncAfter
.
You need to tell the compiler that this reference is either weak
or unowned
(See attached link for more info.), this will enable the instance of self
to be deinitialised even though you have a reference to self
from the closure.
The weak
keyword can be used in cases where you want the closure to run and make actions that doesn't require a reference to self
. This is helpful to use if you don't know if self
is alive or not.
The unowned
keyword can be used in cases where you don't need the closure to run without a reference to self
. This must be used in cases where you know self self
is still alive.
Getting a weak
or unowned
reference of self in the closure can be achieved like in the example below:
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[weak self] in
self?.doSomething()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[unowned self] in
self.doSomething()
}
It's worth mentioning that if you're not using a deadline, but calling .async { ... }
directly does not result in capturing self and therefore can be used safely without defining weak/unowned self
.
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