If I would nest two timers that are both properties of the class they are referenced in, would I have to call [weak self]
in both or just the first timer block?
timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
print(self)
self?.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
print(self)
}
}
As long as you don't convert the weak
reference into a strong one outside of your nested closure, the weak
reference is passed into the nested closure, so you don't need to make it weak
again.
So the below code is just fine:
timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
print(self)
self?.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
print(self)
}
}
You can confirm this by the fact that you'll get the warning
Expression implicitly coerced from 'Timers?' to 'Any'
On both print
statements.
You always need to create a weak reference in the outer-most closure where you reference self, otherwise your outer closure will create a strong-reference cycle, so whether the inner one creates a weak reference or not won't make a difference.
This creates a strong reference cycle, since to access timer2
, you use a strong reference to self
.
timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
print(self)
self.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
print(self)
}
}
As long as you convert the weak reference to a strong one using a variable with a different name, the reference to self
will be weak
and hence you don't need to make it weak
again.
So the below code is also free of strong reference cycles.
timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
guard let strongSelf = self else { return }
print(strongSelf)
strongSelf.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
guard let self = self else { return }
print(self)
}
}