Tometoyou
Tometoyou

Reputation: 8376

Why is a retain cycle being caused?

I am using Eureka to set up my table view. I have a section with a header:

Section() { [weak self] in
    guard let strongSelf = self else { return }
    var header = HeaderFooterView<MyView>(.nibFile(name: "MView", bundle: nil))
    header.onSetupView = strongSelf.setUpHeader(view:section:)
    $0.header = header
    ...
}

private func setUpHeader(view: MyView, section: Section) {
    // content here doesn't seem to make a difference.
}

For some reason it always sets up a retain cycle on the line header.onSetupView = strongSelf.setUpHeader(view:section:). If I move the code from the setUpHeader(view: MyView, section: Section) function into a block like this, there is no retain cycle:

header.onSetupView = { [weak self] view, section in

}

Why is this??

Upvotes: 1

Views: 152

Answers (1)

Rob Napier
Rob Napier

Reputation: 299355

header.onSetupView = strongSelf.setUpHeader(view:section:)

This line creates a strong reference to strongSelf, which is a strong reference to self, so transitively that creates a strong reference to self in the onSetupView closure.

Saying it another way, what you've written here is the same as:

header.onSetupView = { view, section in
    strongSelf.setupHeader(view: view, section: section)
}

And since strongSelf is a strong reference to self, that's the same thing as strong reference to self:

header.onSetupView = { view, section in
    self.setupHeader(view: view, section: section)
}

And just one more way to say it: self cannot be deallocated before strongSelf is, because then strongSelf would be an invalid reference.

Upvotes: 1

Related Questions