Boon
Boon

Reputation: 41480

Must all variable or lazy variable initializer in Swift include weak self?

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
  }
}()

Upvotes: 2

Views: 2156

Answers (1)

Brett
Brett

Reputation: 2635

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

Upvotes: 11

Related Questions