While the accepted answer explains how you handle weak self
according to different scenarios, I feel like it fails to properly explain why you gotta unwrap weak
references and why use weak
references in the first place. Understanding this chain will automatically make you understand why you have to unwrap a weak self
Closures are awesome, if you handle them properly
The usual major caveat(that beginners often tend to overlook) with closures is that they capture the class they are declared on, IF you use something that belongs to the class inside the closure.
I'll explain the 'capturing' process:
1) The closures that you declare as a property for your class are escaping
closures.
2) To explain what escaping
closures are, they don't deallocate with the block they are declared at. They instead escape and outlive the block to provide you callback.
(Also, you might have noticed that the compiler asks you to specify @escaping
exquisitely when you pass a closure as a function parameter to provide completion blocks, and this is exactly why it asks you to)
3) Hence, using something that belongs to the class(such as a property) inside an escaping
closure allows the closure to capture(retain in memory) the whole class to provide you callback, and this leads to retain cycles
Here's an example: (The same one from the link that I'll share)
Say you have this class
:
class ListViewController: UITableViewController {
private let viewModel: ListViewModel
init(viewModel: ListViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
viewModel.observeNumberOfItemsChanged {// Assume this to be some closure that I have in my viewModel
// This will cause a retain cycle, since our view controller
// retains its view model, which in turn retains the view
// controller by capturing it in an escaping closure.
self.tableView.reloadData()
}
}
}
All these happen because the closure holds a strong reference to your class. To break this strong reference, you use weak self
in your callback. The weak
keyword in a nutshell deallocates the class object if it remains unused for a considerable amount of time and helps break retain cycles
And now, to your question: (You might know the answer already if you made it this far :-))
You have to unwrap weak self
because it might no longer be in memory, simple as that!
Finally, here's the link that I was talking about: Capturing objects in Swift closures
NOTE:
In certain cases, you can almost be pretty sure that the captured object will remain in memory by the time you receive callbacks, but want self
to be deallocated after that. In those cases, you can use unowned self
instead of weak self
to break free from the unwrapping hassle. This is almost the same as unwrapping an optional and hence will crash if self
is deallocated