What is this `[unowned self] in` Swift code doing? - swift

I came across this Swift code that I don't understand. What is the navigationCallback being assigned to? What is [unowned self]? I think I would understand this better if I could see the equivalent example in Objective-C.
navigationCallback = { [unowned self] in
previousNavigationCallback?()
if self.state != .Canceled {
callback()
}
}

What is the navigationCallback being assigned to?
The stuff in curly braces constitutes an anonymous function. It's like a block in Objective-C.
What is [unowned self]?
The stuff in square brackets preceding in in the anonymous function's capture list. It prevents a retain cycle by bringing self into the anonymous function unretained. unowned is like an assign property policy in Objective-C (non-ARC weak). In Objective-C you'd typically do the weak-strong dance in order to do something similar.

That construct is called a "Capture list". As Matt says, it lets the closure/block/anonymous function have an unowned reference to self inside the block. It lets you avoid retain cycles caused by closures that have a strong reference to the object that creates them, when the creating object also has a strong reference to the closure.
This is covered in detail in Apple's Swift iBook. Here's a brief excerpt:
Resolving Strong Reference Cycles for Closures You resolve a strong
reference cycle between a closure and a class instance by
defining a capture list as part of the closure’s definition. A capture
list defines the rules to use when capturing one or more reference
types within the closure’s body. As with strong reference cycles
between two class instances, you declare each captured reference to be
a weak or unowned reference rather than a strong reference. The
appropriate choice of weak or unowned depends on the relationships
between the different parts of your code.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2).” iBooks. https://itun.es/us/jEUH0.l

Related

Weak Self in GCD, accessing TableView property of self

I see a lot of code like this:
DispatchQueue.main.async {
self.tableView.reloadData()
}
In this context, where tableView is a property of self, should one instead ensure weak self is captured like this:
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
I think so, but this type of "unsafe" code is so ubiquitous across codebases I wonder if I'm missing something?
You said:
In this context, where tableView is a property of self, should one instead ensure weak self is captured like this:
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
No, you don’t actually need to use weak reference to self in this case. There is no persistent strong reference cycle here. The worst that would happen (in the absence of weak reference) is that it will keep a strong reference to self until the dispatched block finishes running. But that closure will generally run practically immediately and the fleeting strong reference will be eliminated very quickly.
So, as such, no, you don’t have to use weak reference here. It is not technically incorrect to do so, but adds a syntactic noise for practically no benefit. Yes, we should be diligent about breaking potential strong reference cycles with weak references, but this is not one of those cases.
By the way, the choice of the term “unsafe” muddles the topic a bit. “Unsafe” has a very specific meaning when talking about memory references: It generally refers to dangling references to deallocated objects when not using runtime safety checks. As The Swift Programming Language: Automatic Reference Counting says (emphasis from original):
Swift also provides unsafe unowned references for cases where you need to disable runtime safety checks—for example, for performance reasons. As with all unsafe operations, you take on the responsibility for checking that code for safety.
You indicate an unsafe unowned reference by writing unowned(unsafe). If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation.
Obviously, both strong and weak references are safe (the former keeps the object from being released, the latter sets its references to nil when the object is deallocated). Even unowned references often employ runtime safety checks (though it still results in runtime error if you use a unowned reference after the object is deallocated). An “unsafe” reference is used in high-performance scenarios, where you are absolutely confident in your unowned references are being handled properly and that you’re willing to run your code without runtime safety checks.
I suspect you didn’t mean “unsafe” in this context, but I mention it so that you are aware of the very specific meaning that this word has within the context of ARC and memory management.

Should function arguments be weak?

I have following case with weak reference:
function hello(to persons: [Person]) {
/// should persons be also weak below?
helloView.didHelloPressed = { [weak self] someFlag in
self?.configurePersons(persons)
}
}
In above code, I captured weakly and I understand that self should be weak because I use its function (configurePersons). But should persons array, which is argument of hello function be also weak? I think yes, but I don't clearly explain it. I thought that if self is not nil, then persons also will not be nil and it doesn't make sense to make it weak.
Weak references aren't something you should use "just because I see a closure".
Even with closures, and even with self, there are plenty of times where you don't want a weak reference.
Weak references exist to break strong reference cycles. That's it. The captured variables of closures are one kind of strong reference that exists. If a closure strongly captures a variable, nothing scary happens.
The issue is when a closure captures foo, and then you store the closure inside the foo. That's a strong reference cycle, which needs to be broken. One of the two references needs to be weak, so either you should hold the closure weakly in the foo, or you should capture the foo weakly in the clsoure.
Your persons has type Array<Person>. There could be a strong reference cycle if one of those Person objects has a strong reference to helloView, which itself has a strong reference to its didHelloPressed closure. But that would be very weird, and is almost certainly (hopefully!) not what you're doing, so no, there's no need to weakly capture persons.
Even more, depending on the relationship between helloView and what self is in this context, it's entirely possible that you might want to capture self strongly, too.
Array is a value type in Swift. It not managed by ARC. So, the answer is No.
In Swift, function parameters are strongly referenced. I am also not sure there’s a way to pass any parameter as a weak reference. In this case, there is no cycle for calling the function hello(to: person). So, the answer is No.

What does the [something] syntax in Swift mean when working with closures?

Normally when capturing reference to a property in a closure I would do something like this -
foo { [weak self] in
self?.bar()
}
But I have also seen this written as -
foo { [bar] in
bar()
}
What is meant by [bar] and how is this different from capturing a weak self?
That [bar] part is a capture list.
It instructs the closures as how values should be captured. When you enter variables in the bracket right before the keyword in, the closure is no longer referencing the original variables, instead the closure creates its own copy within the closure block.
That's a capture list, which can be used to resolve strong reference cycles.
If a closure captures variables by reference (which it does for all reference types), the closure could create a strong reference cycle by being the last object to hold a reference to the captured variable.
A weak reference means that it doesn't increase the reference count of the object, so if the last reference to an object is a weak one, its reference count is 0 and hence ARC will deallocate it. This is especially useful for escaping closures, whose lifetime might be longer than the lifetime of the referenced/captured objects and hence the closure could end up holding the last reference to the object and hence wouldn't allow ARC to deallocate it.

Swift - Capture List self clarification

After reading some articles and developer guide of apple, i'm still confused about Capture List in closure.
What does it mean "capture", how does it work behind the scene in terms of unowned self and weak self? how the closure use self without owning the object?
I thought it like making a copy of that object so when it get finished it's passed from the stack like value type, but i guess that i'm wrong.
I'm hoping that someone here can make it more easier and clear for understanding, or linked me to a good article that answering this specific question.
Thanks for advance
My understanding, and it might be a bit simplified, is that it is about ownership and holding on to an object, meaning that as long as we claim ownership of an object it can not be freed from memory even another part of the code sets it to nil or similar.
With weakwe say that it is okay to destroy the object and that we will only use it if it is still around.
So when declaring self as weak in a closure we say that if self is still around when it's time to execute the closure we do so normally otherwise the closure will silently be ignored without generating an error.
It's mainly to do with reference counting. Any instance that is used inside a closure (but was declared outside) is strongly referenced (i.e. its reference count is incremented). This can lead to retain cycles, e.g.
class MyClass {
var myClosure: (() -> Void)!
init() {
myClosure = {
self.foo()
}
}
func foo() {
}
}
In the above example the instance of MyClass retains a reference to myClosure and vice versa, meaning that the MyClass instance will stay in memory forever.
You can also have more complex/harder-to-spot retain cycles, so you need to really pay attention and if you ever have any doubts add some print calls to your class' deinit methods just to make sure (or use Instruments).
In order to avoid these issues you can mark objects being captured in closures as unowned or weak. This means that their reference count won't be increased and you can avoid these retain cycles. The above example could have either been done this way:
myClosure = { [weak self] in
self?.foo()
}
or, better yet for this example, this way:
myClosure = { [unowned self] in
self.foo()
}
While the first way is always safe and what you will more likely do, the unowned version is easy to reason in this example because you know that myClosure won't outlive self. However, if you're not 100% sure that self will always outlive the closure use weak.
Also note that you can mark how to capture multiple objects used inside the closure, just separate it by commas, e.g.
myClosure = { [weak self, unowned bar] in
self?.foo(bar)
}
If we keep in mind that captured values are strong references in closures by default, we can assume that this can create retain cycles (bad stuff).
A capture list is an array of variables you can pass into a closure. The purpose of capture lists is to change the strenght of the variables that are passed in. This is used to break retain cycles.
For instance:
// strong reference
[label = self.myLabel!] in
// weak reference
[weak label = self.myLabel!] in
// unowned reference
[unowned self] in

Is weak self needed in NSKeyValueObservation observe() closure?

I have:
private var statusLabel: UILabel!
private var errorObserver: NSKeyValueObservation?
self.errorObserver = self.viewModel.observe(\.errorString)
{ [weak self] (viewModel, change) in
self?.statusLabel.text = viewModel.errorString
}
Is [weak self] needed here?
Short answer: Yes, you do need the [weak self]. Not having to explicitly remove the observer in deinit is a nice convenience that makes sure the Observation Center does not send notifications to de-initialized observers, but does not absolve you from having to manage memory for the closure.
Apple's Official Documents (The Swift Programming Language 4.0.3) states:
By default, a closure expression captures constants and variables from its surrounding scope with strong references to those values. You can use a capture list to explicitly control how values are captured in a closure.
A capture list is written as a comma-separated list of expressions surrounded by square brackets, before the list of parameters. If you use a capture list, you must also use the in keyword, even if you omit the parameter names, parameter types, and return type.
....
If the type of the expression’s value is a class, you can mark the expression in a capture list with weak or unowned to capture a weak or unowned reference to the expression’s value.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4.0.3).” iBooks.
If you do not mark the expression self in a capture list, a strong reference cycle will be created. A strong reference cycle is created because classes are reference types, and closures are reference types. When the body of the closure refers to an instance of a class, a reference to the class instance is created by the closure. By default, this is a strong reference, unless you use a capture list to define a different type of reference. The official notes even say:
Swift requires you to write self.someProperty or self.someMethod() (rather than just someProperty or someMethod()) whenever you refer to a member of self within a closure. This helps you remember that it’s possible to capture self by accident.
In your case, you are referencing a label inside the body of the closure. The fact that you need to write
self?.statusLabel.text = viewModel.errorString
instead of simply
.statusLabel.text = viewModel.errorString
is a hint to you to use self inside a capture list.