2

I have seen a lot of code that uses closure to initialize a var or lazy var which refer to self without the weak self syntax. Doesn't that create a risk of a retain cycle? Why doesn't the compiler flag that? Should it be a mandatory thing to always use weak self or unowned self when using closure of any kind as a safety measure?

e.g.

class Test {
  lazy var tableView: UITableView = {
    let tableView = UITableView(frame: self.view.bounds, style: .plain)
    tableView.delegate = self
    tableView.dataSource = self

    return tableView
  }
}()
Boon
  • 40,656
  • 60
  • 209
  • 315
  • 1
    Related: [Lazy initialisation and retain cycle](http://stackoverflow.com/q/38141298/2976878) – Hamish Nov 24 '16 at 21:29

1 Answers1

11

Lazy variables that aren't closure properties are not retained by anything so there is no need to use [unowned self] here:

class Test {
    lazy var tableView: UITableView = {

        let tableView = UITableView(frame: self.view.bounds, style: .plain)
        tableView.delegate = self
        tableView.dataSource = self
        return tableView
    }()
}

This is not to be confused with closure properties that are lazily defined! Then the closure captures self, which will create a retain cycle. In this case you are creating a strong reference via self.view.bounds so you should use [unowned self] (you know in this case that the tableView shouldn't exist if the Test object doesn't).

class Test {
    lazy var tableView: () -> UITableView = {
        [unowned self] in

        let tableView = UITableView(frame: self.view.bounds, style: .plain)
        tableView.delegate = self
        tableView.dataSource = self    
        return tableView
    }
}

Further reading: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

https://krakendev.io/blog/weak-and-unowned-references-in-swift

Brett
  • 2,635
  • 22
  • 35