This is allowed in Swift 5.0:
class Person {
unowned var child: Person?
}
This is supported by this release notes:
unowned and unowned(unsafe) variables now support Optional types.
(47326769)
I understood exactly the difference between weak and unowned in Swift 4.2 and before. However, I am not sure why Apple decided to make the unowned an optional type. Even in the docs (which are docs for Swift 5.0) this implemented 'proposal' (where can I even find that proposal with the motivation to add optional unowned references?) isn't updated, because it says:
An unowned reference is expected to always have a value. As a result,
ARC never sets an unowned reference’s value to nil, which means that
unowned references are defined using non-optional types.
Above isn't true anymore. The only functional difference that Apple states is that an unowned reference is expected to have an equal or longer lifetime than the object holding that reference. Well, I am curious about the technical use of this.
What difference does it make when I use a weak reference vs an optional unowned reference? Or is the only difference that optional unowned should be used when the referencing object has a longer lifetime? I would expect there must be more...
You've misunderstood the release note and the meaning of the change in the language.
why Apple decided to make the unowned an optional type
They didn't. You can, and usually will, still say
unowned let owner : MyViewController
The only change here is that the unowned variable can be an Optional, which was illegal previously. This change takes care of an annoying edge case, that's all.
Above isn't true anymore
Yes, it is. Things are completely unchanged from before:
Weak references must be typed as Optional; they do not retain the object referred to, but they track the object referred to, and revert to nil if that object goes out of existence.
Unowned references do not retain the object referred to and do not track the object referred to, so it's up to you to prevent that object from going out of existence or you may end up with a dangling pointer and a crash.
The only thing that's changed is that there used to be an additional rule that an unowned reference type could not be an Optional. That rule is now gone.
As you rightly point out, if the unowned reference type is an Optional, this must be a var reference, not a let reference (because having this be an Optional would make no sense if you didn't have the power to change it from nil to an actual value and vice versa).
A typical use case is very much like what you yourself provided:
class Node {
unowned var parent: Node?
}
It seems reasonable to say that this Node may or may not have a parent (because it might be at the top of the graph), but that if it does have a parent, that parent should be unowned (a parent should retain its child, but a child should not retain its parent). Previously, the only way to say that was to make this a weak reference, which entails some unnecessary overhead, and is otiose, because we can absolutely guarantee that if a node has a parent, the parent will outlive the child. Now, you can say what you mean, which is generally a good thing.
Related
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.
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.
This question already has answers here:
What is the difference between a weak reference and an unowned reference?
(7 answers)
Swift. Is the (absolutely) sole specific advantage of unowned over weak, performance?
(4 answers)
Closed 5 years ago.
I am working on Swift and I have little bit confusion on usage of unowned and weak keywords for memory management in Swift.
Can any one help me to understand where to use unowned ?
Thanks in advance!
The most important difference is that unowned variables are very dangerous in Swift.
weak is an optional type, unowned is NOT.
This means that you can create code that uses weak as part of the logic. (think of asynchronous actions that take place only if a view controller is still being shown on the screen, when the code is ran, if the reference is "weak" it will fail silently without causing any other issues if the code is written correctly)
On the other hand, when a variable is unowned you are basically saying that this variable will always refer to something. And unlike weak, if you call it and there's nothing it will crash.
You generally never wanna use unowned. (I haven't come across any case where I had to). On the other hand, "weak self" variables are quite common when writing blocks.
You can see a good explanation on this question:
Shall we always use [unowned self] inside closure in Swift
EDIT: Actually, check the first and second most voted answers. They provide a clear explanation on WHEN to use unowned and how it works. The second even has pictures!
As per apple docs
There are some pretty good examples given on the developer website, check this link
As far as blocks are concerned as per Apple Docs:
Define a capture in a closure as an unowned reference when the closure
and the instance it captures will always refer to each other, and will
always be deallocated at the same time.
Conversely, define a capture as a weak reference when the captured
reference may become nil at some point in the future. Weak references
are always of an optional type, and automatically become nil when the
instance they reference is deallocated. This enables you to check for
their existence within the closure’s body.
To conclude 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.”
Weak and Unowned references are used to prevent retain cycles in the situation where two objects each hold a reference to the other. I get the use of weak but I do not get the use of unowned. Here is Apple's example of a situation where one of the two objects should use an unowned reference:
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
}
}
The idea is that a credit card cannot exist without a customer. Therefore a credit card can dispense with the optional unwrapping that the use of a weak reference would entail, and can instead use an unowned reference. Hmmm ... so why not use a strong reference? If all other references to the customer were to go away (which is not supposed to happen?) then the credit card's use of an owned reference would result in a crash; whereas its use of a strong reference would result in a memory leak. Huh? A choice between two evils? Better to crash because that is more likely to be noticed during development and testing?
Please help with some insight. Thanks.
Better to crash because that is more likely to be noticed during development and testing?
Yes.
Well, not exactly.
The idea is that your app's design should ensure that no CreditCard instance outlives it's respective Customer instance. When you use unowned, you trust yourself to have a design in play that logically guarantees a crash-free execution.
Now, why would anyone ever use unowned over weak? Simple! unowned removes the whole hassle of Optional unwrapping, and if you know that your CreditCard instance will never outlive it's respective Customer instance, then you should use unowned by all means.
unowned is actually much better than weak, in those situations where it is appropriate (i.e. it is certain that the unowned object will not go out of existence), because:
A weak reference must be an Optional, which may need unwrapping, and
A weak reference entails large amounts of overhead in order to track the reference and change it to nil if it is deallocated, whereas an unowned reference entails zero overhead.
It's actually not a problem because as it stands, the unowned reference does not create any sort of strong reference cycle. When the Customer object is deallocated, its CreditCard will be immediately deallocated as well. Your CreditCard will never get a chance to reference that deallocated Customer.
Very interesting question. Here is some difference between Weak and Unowned References according to Apple's documentation.
Weak References
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. This behavior prevents the reference from becoming part of a strong reference cycle.
Unowned References
Like a weak reference, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is used when the other instance has the same lifetime or a longer lifetime.
Your question's answer :
weak can become nil, whereas unowned is presumed to never become nil, therefore weak will be optional where as unowned does not need to be optional.
In this case Customer may or may not have CreditCard but no CreditCard should exist without Customer.
Okay, I finally get it:
The last reference to Customer (other than Credit Card's) is set to nil.
ARC checks the Customer's reference count:
Credit Card has a strong reference - Customer's reference count will be 1 so ARC will not deallocate it. Result - memory leak.
or, Credit Card has an unowned reference - Customer's reference count will be 0 so ARC will deallocate it. Doing so will cause Credit Card's reference count to go to 0 causing it to be deallocated. Hence, Credit Card will never have an opportunity to dereference its now nil unowned reference. Result - no crash.
So, if we have designed our code such that holder of the reference (CreditCard) is guaranteed to be deallocated when the referenced object (Customer) is deallocated then we have the kind of scenario wherefore unowned references were designed.
Thanks #Bob
Quick search on this topic revelead this link to another SO answer.
Basically weak references can or cannot be nil, where as unowned references assume that it will never be nil.
You can learn more about them in the Apple docs.
I'm guessing the reasoning behind using an unowned in this case is solely because the unowned is presumed to never be nil (without a customer).
I'm confused about the type requirements and declaration restrictions for Swift capture specifiers. The documentation says that weak references must be var and "of optional type", and that unowned references must be of non-optional type. But Apple's own API reference has examples of unowned(unsafe) references declared as optionals, while the Xcode interface builder creates weak outlets and actions that are implicitly unwrapped (which is not always clearly "of optional type" in the language reference).
What types are required for each of the Swift capture specifiers? Which must be var and which can be let?
FWIW, I think its
weak can be Type? or Type!, but not Type; and must be var
unowned(safe) (same as unowned) must be Type; and may be let
unowned(unsafe) can be Type? or Type!; and may be let
but I'm far from sure.
First the Cocoaor Cocoa touch APIs are imported in swift fromobjective-c`. They are mapped in swift with best possible ways.So that both can interoperable.
Those unowned(unsafe) properties are marked as assign in ObjC. These are unsafe and ARC doesn't retain the object, and it doesn't make sure the reference gets reset to nil if the object is deallocated. These are old apple API and not changed with ARC and remain asassignbut you should makedelegateweak`
Do not look for headers for best practices in swift they have made many tricks to make swift and objective-c interoperable and if you do what headers do than you loose all safety swift proveide.
You are right
weak should be optional as contain nil automatically if objects get deallocate and no other pointer retain it
unowned(safe) should not be optional and will not reset to nilif objects deal-located
unowned(unsafe) can or can not be optional as it not provide any safety by ARC for object deal-location and do not reset to nil.You should not use this in swift program.Use unowned if needed.It is just for interoperability.
weak is always var because it can be changed when objects deallocate and set to nil.
unowned(safe) and unowned(unsafe) can be both var or let as they are dependent on you and run-time will not change these variables.
Note:You can not declare a unowned(unsafe) as optional in swift program.Its for just interoperability and should not be used in swift.They have made this because of assign or unretain properties can be nil