Is it necessary to use [unowned self] in closures of UIView.animateWithDuration(...)?
IosSwiftMemory ManagementUiviewanimationRetain CycleIos Problem Overview
UIView.animateWithDuration(1,
animations: { [unowned self] in
self.box.center = self.boxTopRightPosition
},
completion: { [unowned self] completed in
self.box.hidden = true
})
Is it necessary to avoid memory leak?
Ios Solutions
Solution 1 - Ios
No, it is not needed in this case. animations
and completion
are not retained by self
so there is no risk of strong retain cycle.
Solution 2 - Ios
Well, "necessary" isn't the same as "recommended". If your question is if it's necessary then @Kirsteins' response is fine, however imagine the situation where you want to animate something in your view controller after some work, but your view controller has been released (because it is not in the view hierarchy anymore or any other reason). In this case, if you don't use [weak self]
, your view controller won't get released until finishing the animation because you are retaining it in the animation block, but does it make sense to keep it retained until animating something which is not in the view anymore?
So, in few words, you don need to use a weak
reference to self when animating UIKit, however, you don't need to keep your view retained if it's released, because an animation with no view doesn't make sense, so using weak
is a good option.
Solution 3 - Ios
No it's not needed. As Kirsteins says:
> No, it is not needed in this case. animations and completion are not retained by self so there is no risk of strong retain cycle.
But lhmgrassi says:
> As soon as it be deallocated, the deinitializer will be called and the completion will never be executed.
I don't think this is true. The completion block will always be called. And if you use a strong self your object won't be deallocated until the completion block is executed.
However, if you use a [weak self]
, your object is not (temporary) retained by the completion block and might be deallocated before the completion block is fired. The completion block is still fired but self
is already nil
.
If you use a [unowned self]
in your completion handler, you object might also be deallocated before the completion handler is called, which could result in a crash!
I've made an example illustrating this.
[
Full source can be found on Github
Solution 4 - Ios
@Plabo, as @Kirsteins said, animations and completion are not retained by self, so even if you start a animation and for any reason your view controller has been released, it will deallocated instantaneously. So, you don't need captured 'self'. Consider the silly example bellow:
class ViewController: UIViewController {
@IBOutlet weak var button : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad ViewController")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIView.animate(withDuration: 20, animations: {
self.button.frame = CGRect(x: 0, y: 300, width: 30, height: 30)
}) { finished in
self.button.frame = CGRect(x: 0, y: 100, width: 30, height: 30)
}
}
deinit {
print("deinit ViewController")
}
}
As soon as it be deallocated, the deinitializer will be called and the completion will never be executed.
Solution 5 - Ios
Just the opposite. You want self
to continue to exist long enough for the completion block to be called. Therefore having self
be strong and retained through the escaping completion handler is a good thing.
The worry that usually leads people to use weak self
is a retain cycle. But this isn't that. A retain cycle is when self
retains the closure which retains self
, causing a leak because now self
can never be released. But this is not that situation at all. the closure, and therefore self
, is being retained, but not by self
! So there is some retaining going on, temporarily, but it is good, not bad.
Solution 6 - Ios
It is not needed to use weak/unowned in Animations, GCD or completion handler because :
The external object reference captured by them will only be kept for fixed time, which means it's definitive that it's going to be executed at one point of time. After this, it will be released so there is no chance of reference cycle which leads to memory leak.
As previous answers suggests,
> If animations and completion are not retained by self, then who retains them ?
I didn't find any documentary evidence of this but what I believe is that they are retained by self itself but for a fixed amount of time. After this, the completion executes and release the self, which result the de-allocation of self.
In the retain cycle scenario, the closure is retained by self and self by closures for indefinite time, which is considered as reference cycle and memory leak.