Swift Retention Cycle in Closures and Delegate
Bob Lee
80414

If you capture self within a closure then self will, by definition, never be nil, since the closure has captured a strong reference to it.

As you mentioned, one can use[weak self] to allow self to potentially become nil and thus break retain cycles.

Another reason, however, is that one could capture a strong reference to a view controller… that’s already been dismissed or popped and is no longer on the navigation stack.

Let’s say the user opens an “account” screen that loads data from the web. And let’s say that he’s on a bad connection and he gets tired of waiting, so he closes the screen.

If the network closure that handles the data request captures a strong reference to self, it’s going to create a temporary retain cycle until the request succeeds or times out. Either way, the closure will probably then attempt to update the UI on a viewController that’s no longer on the stack.

Also known as a bad thing.

Use [weak self], however, and the closure can detect that it’s parent UI has been dismissed and react accordingly. (By doing nothing.)

You’d never want to use [unowned self] in such a situation, since it’s entirely possible for the viewController to be dismissed.

That said, if your UI is blocked while the network request is running then you could use unowned, since there’s never a chance for the viewController to be dismissed. (But basically, unowned isn’t needed either, for the same reason. Can’t dismiss so it can’t be nil so might was well keep strong reference.)

Like what you read? Give Michael Long a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.