I've been working on Swift for about half a year, and now I struggle with understanding when to use the [weak self]
to avoid a memory leak. TBH, it was too difficult for me to understand from the document or other people's articles, so I used this video to figure out when to use it.
I kinda understood when to use the [weak self]
but not 100% sure its usage.
In the video, for instance, the guy created an alert controller in the view controller.
class TestVC: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "done", style: .cancel, handler: { _ in
self.doSomething()
}))
present(alert, animated: true)
}
func doSomething() {
// do something
}
}
He explains that
- the view controller creates the alert
- when the done button is pressed, in the handler closure, it references self, which is a view controller.
So in the above, I get I must use [weak self]
to deallocate the view controller.
However, now I'm confused with when not to use the weak self
.
For instance, say I have a view controller with a function to animate the view.
class TestVC: UIViewController {
let testView = TestView()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
changeViewHeight()
}
func changeViewHeight() {
UIView.animate(withDuration: 3) {
self.testView.heightConstraint?.constant = 40
self.view.layoutIfNeeded()
}
}
}
So in the code above, since the TestVC has a reference to changeViewHeight function, and in the completion block of the animate function, it points back to TestVC using self
, should I change it to [weak self]
?
Also, I think any function with a completion block has a chance to use self
in the completion block, but that time is the retain cycle is happening and I should consider using [weak self]
whenever I use self
in the completion block? (which I guess it's not, but cannot explain why, so if someone can explain please let me know.)