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.
Related
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.
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.
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
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
Swift has:
Strong References
Weak References
Unowned References
How is an unowned reference different from a weak reference?
When is it safe to use an unowned reference?
Are unowned references a security risk like dangling pointers in C/C++?
Both weak and unowned references do not create a strong hold on the referred object (a.k.a. they don't increase the retain count in order to prevent ARC from deallocating the referred object).
But why two keywords? This distinction has to do with the fact that Optional types are built-in the Swift language. Long story short about them: optional types offer memory safety (this works beautifully with Swift's constructor rules - which are strict in order to provide this benefit).
A weak reference allows the possibility of it to become nil (this happens automatically when the referenced object is deallocated), therefore the type of your property must be optional - so you, as a programmer, are obligated to check it before you use it (basically the compiler forces you, as much as it can, to write safe code).
An unowned reference presumes that it will never become nil during its lifetime. An unowned reference must be set during initialization - this means that the reference will be defined as a non-optional type that can be used safely without checks. If somehow the object being referred to is deallocated, then the app will crash when the unowned reference is used.
From the Apple docs:
Use a weak reference whenever it is valid for that reference to become
nil at some point during its lifetime. Conversely, use an unowned
reference when you know that the reference will never be nil once it
has been set during initialization.
In the docs, there are some examples that discuss retain cycles and how to break them. All these examples are extracted from the docs.
Example of the weak keyword:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
weak var tenant: Person?
}
And now, for some ASCII art (you should go see the docs - they have pretty diagrams):
Person ===(strong)==> Apartment
Person <==(weak)===== Apartment
The Person and Apartment example shows a situation where two properties, both of which are allowed to be nil, have the potential to cause a strong reference cycle. This scenario is best resolved with a weak reference. Both entities can exist without having a strict dependency upon the other.
Example of the unowned keyword:
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}
class CreditCard {
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}
In this example, a Customer may or may not have a CreditCard, but a CreditCard will always be associated with a Customer. To represent this, the Customer class has an optional card property, but the CreditCard class has a non-optional (and unowned) customer property.
Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard
The Customer and CreditCard example shows a situation where one property that is allowed to be nil and another property that cannot be nil has the potential to cause a strong reference cycle. This scenario is best resolved with an unowned reference.
Note from Apple:
Weak references must be declared as variables, to indicate that their
value can change at runtime. A weak reference cannot be declared as a
constant.
There is also a third scenario when both properties should always have a value, and neither property should ever be nil once initialization is complete.
And there are also the classic retain cycle scenarios to avoid when working with closures.
For this, I encourage you to visit the Apple docs, or read the book.
Q1. How is an “Unowned reference” different from a “Weak Reference”?
Weak Reference:
A weak reference is a reference that does not keep a strong hold on
the instance it refers to, and so does not stop ARC from disposing of
the referenced instance. Because weak references are allowed to have
“no value”, you must declare every weak reference as having an
optional type. (Apple Docs)
Unowned Reference:
Like weak references, an unowned reference does not keep a strong hold
on the instance it refers to. Unlike a weak reference, however, an
unowned reference is assumed to always have a value. Because of this,
an unowned reference is always defined as a non-optional type. (Apple Docs)
When to Use Each:
Use a weak reference whenever it is valid for that reference to become
nil at some point during its lifetime. Conversely, use an unowned
reference when you know that the reference will never be nil once it
has been set during initialization. (Apple Docs)
Q2. When is it safe to use an “unowned reference”?
As quoted above, an unowned reference is assumed to always have a value. So you should only use it when you are sure that the reference will never be nil. Apple Docs illustrate a use-case for unowned references through the following example.
Suppose we have two classes Customer and CreditCard. A customer can exist without a credit card, but a credit card will not exist without a customer, i.e. it can be assumed that a credit card will always have a customer. So, they should have the following relationship:
class Customer {
var card: CreditCard?
}
class CreditCard {
unowned let customer: Customer
}
Q3. Are “unowned reference” reference an security risk like “dangling pointers” in C/C++
I don't think so.
Since unowned references are just weak references that are guaranteed to have a value, it shouldn't be a security risk in any way. However, if you try to access an unowned reference after the instance that it references is deallocated, you will trigger a runtime error, and the app will crash.
That's the only risk I see with it.
Link to Apple Docs
If self could be nil in the closure use [weak self].
If self will never be nil in the closure use [unowned self].
If it's crashing when you use [unowned self] then self is probably nil at some point in that closure and you probably need to use [weak self] instead.
Check out the examples on using strong, weak, and unowned in closures:
https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html
Extracts from link
Few Concluding points
To determine if you even need to worry about strong, weak, or
unowned, ask, “Am I dealing with reference types”. If you’re working
with Structs or Enums, ARC isn’t managing the memory for those Types
and you don’t even need to worry about specifying weak or unowned for
those constants or variables.
Strong references are fine in hierarchical relationships where the parent references the child, but not vice-versa. In fact, strong references are the most appropraite kind of reference most of the time.
When two instances are optionally related to one another, make sure
that one of those instances holds a weak reference to the other.
When two instances are related in such a way that one of the
instances can’t exist without the other, the instance with the
mandatory dependency needs to hold an unowned reference to the other
instance.
Both weak and unowned references will not impact the reference count of the object. But weak reference will always be optional i.e. it can be nil, whereas unowned references can never be nil so they will never be optional. When using an optional reference you will always have to handle the possibility of the object being nil. In case of an unowned reference you will have to ensure that the object is never nil. Using an unowned reference to a nil object will be similar to forcefully unwrapping an optional that is nil.
That said it is safe to use an unowned reference where you are sure that the object’s lifetime is more than the reference’s. If that is not the case it is better to use a weak reference instead.
As for the third part of the question, I don’t think unowned reference is similar to a dangling pointer. When we talk about reference count, we usually refer to strong reference count of the object. Similarly swift maintains unowned reference count and weak reference counts for the object (weak reference points to something called a "side table" rather than the object itself ). When the strong reference count reaches zero, the object gets deinitialised, but it cannot be deallocated if the unowned reference count is more than zero.
Now a dangling pointer is something that points to a memory location that has already been deallocated. But in swift since the memory can only be deallocated as long as there is an unowned reference to the object, it cannot cause a dangling pointer.
There are a lot of articles that discuss swift memory management in more detail. Here is one.
Unowned references are a kind of weak reference used in the case of a Same-Lifetime relationship between two objects, when an object should only ever be owned by one other object. It's a way to create an immutable binding between an object and one of its properties.
In the example given in the intermediate swift WWDC video, a person owns a credit card, and a credit card can only have one holder. On the credit card, the person should not be an optional property, because you don't want to have a credit card floating around with only one owner. You could break this cycle by making the holder property on the credit a weak reference, but that also requires you to make it optional as well as variable (as opposed to constant). The unowned reference in this case means that although CreditCard does not have an owning stake in a Person, its life depends on it.
class Person {
var card: CreditCard?
}
class CreditCard {
unowned let holder: Person
init (holder: Person) {
self.holder = holder
}
}
Use unowned when you are sure self can never be nil at the point you accessing self at that point.
Example (you can of course add the target directly from MyViewController, but again, it's a simple example).:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myButton = MyButton { [unowned self] in
print("At this point, self can NEVER be nil. You are safe to use unowned.")
print("This is because myButton can not be referenced without/outside this instance (myViewController)")
}
}
}
class MyButton: UIButton {
var clicked: (() -> ())
init(clicked: (() -> ())) {
self.clicked = clicked
// We use constraints to layout the view. We don't explicitly set the frame.
super.init(frame: .zero)
addTarget(self, action: #selector(clicked), for: .touchUpInside)
}
#objc private func sendClosure() {
clicked()
}
}
Use weak when there is a possibility self can be nil at the point you accessing self.
Example:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NetworkManager.sharedInstance.receivedData = { [weak self] (data) in
print("Can you guarentee that self is always available when the network manager received data?")
print("Nope, you can't. Network manager will be alive, regardless of this particular instance of MyViewController")
print("You should use weak self here, since you are not sure if this instance is still alive for every")
print("future callback of network manager")
}
}
}
class NetworkManager {
static let sharedInstance = NetworkManager()
var receivedData: ((Data) -> ())?
private func process(_ data: Data) {
// process the data...
// ... eventually notify a possible listener.
receivedData?(data)
}
}
Cons of unowned:
More efficient than weak
You can (well, you are forced) to mark the instance as immutable (not anymore since Swift 5.0).
Indicates to the reader of your code: This instance has a relationship to X and it can't live without it, but if X is gone, I am gone too.
Cons of weak:
More safe than unowned (since it can't crash).
Can create a relationship to X that goes in both ways, but both can live without each other.
If you aren't sure, use weak. Wait, I mean ask here on StackOverflow what you should do in your case! Using weak all the time when you shouldn't is just confusing for you and the reader of your code.