1

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.)

Yuuu
  • 715
  • 1
  • 9
  • 32
  • Usually : use `[weak self]` when it's inside an instance function, and you don't need it when it's a class function. But there shouldn't be issue about writing `[weak self]` even if it's not needed. – Larme Jan 17 '22 at 09:39
  • @Larme Thank you so much for the quick response. So, you mean the instance function `changeViewHeight` in my example code causes the memory leak and I should use `[weak self]`? like, [weak self] self?.testView.heightConstraint?.constant = 40 – Yuuu Jan 17 '22 at 10:00
  • I meant that `UIView.animate(withDuration:completion:)` is a class method, so in theory it shouldn't capture `self`. It's known that it won't capture it, but bad implementation of class method could cause a retain, it depends on how it's implemented. – Larme Jan 17 '22 at 10:10
  • The general rule to use `[weak self]` is to when there is a chance of retain cycle meaning when two objects are owning each other. In your case, `testView` is captured by `UIView.animate` for modification but not vice versa so `weak` is not needed. – Pawan Rai Jan 17 '22 at 10:20
  • @Larme Ahh, now I get what you mean. – Yuuu Jan 18 '22 at 01:30

0 Answers0