In most cases, self
is a View Controller or some other semi-persistent object. View Controllers are fairly expensive memory-wise, given how much state they govern, including the view hierarchy. When a View Controller is dismissed from the App's navigation flow, its resources really need to be freed. So the design pattern is to always pay attention to self
, so avoid excess references to the VC. For example if the closure lives on for a long time, but the VC is dismissed from navigation, the VC and its associated resources chew up memory uselessly: a memory leak.
In contrast, local variables to a function only have a longer life with respect to the contained closure -- their initial reference count is guaranteed to decrement as soon as the containing function exits. So the closure alone can manage references to it and not be concerned with its App-wide lifecycle.
owned
vs. weak
is really a different question. It depends on your App design -- there's no formulaic answer. unowned
, like weak
, does not increment the retain count of captured objects in the closure. However that leaves the possibility that the captured object ends up with a retain count of 0, and will be deallocated before the closure runs, risking a crash. So you need to be sure, if you say unowned
, that something else is always taking ownership responsibility. In contrast, declaring self
as weak
acknowledges the object as volatile, and forces you to check (if let
...) if the object was deallocated.
Also, I didn't check the related links thoroughly, but I'm sure I'm repeating a lot of what has been said before. Read the highly upvoted posts first.
Shall we always use [unowned self] inside closure in Swift
optional closure property in Swift
EDIT, PERHAPS THE REAL ISSUE
Your book's code makes no sense, because the manual specifically says:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html
This distinction [leaving a variable out of the capture list entirely,
versus including it, but with no weak/unowned designation] is not
visible when the captured variable’s type has reference semantics. For
example, there are two things named x in the code below, a variable in
the outer scope and a constant in the inner scope, but they both refer
to the same object because of reference semantics.
In other words, because ac
is a reference type object, including it "bare" in the capture list does nothing.
I believe the book is in error, and it should say [unowned self, unowned ac]
.
My reasoning is: UIAlertController ac
-> strong reference to submitAction
(via addAction
) -> strong reference to anonymous closure -> strong reference to ac
. Unless one of those is internally declared as weak
just for this purpose, unowned ac
is necessary. Too bad some of that is closed source and we cannot check for sure. The documentation is not specific so we have to assume those are all stored strongly in the library code.