15

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...

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
J. Doe
  • 12,159
  • 9
  • 60
  • 114

1 Answers1

18

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thus for example everything in my explanation http://www.apeth.com/swiftBook/ch05.html#_weak_references and http://www.apeth.com/swiftBook/ch05.html#_unowned_references is still true, except that the words "in fact, it [an unowned reference] _cannot_ be an Optional" should be deleted. – matt Feb 24 '19 at 14:38
  • Is there btw any reason I must mark the optional unowned reference as 'var'? Why isn't let allowed? The following error appears when trying to do that: ''unowned' must be a mutable variable, because it may change at runtime'. I am not sure why this is the case, because normally an non-optional unowned let could be nil also (which kinda indicates a programming error, but that aside). – J. Doe Feb 24 '19 at 14:47
  • "because normally an non-optional unowned let could be nil" Those are extremely strange words. Can you explain a bit more? In Swift, the _only_ thing that can _ever_ be `nil` is an Optional; that is what `nil` is, i.e. it's a possible value of an Optional. So how can you put "non-optional" and "nil" together in a sentence like that? – matt Feb 24 '19 at 15:08
  • When I mark an object as `let unowned` it is possible that the object is nil (the object has deallocated). This means I got a `let unowned` reference that has a non-optional type that points to nothing (nil). This indicates that the reference to that object actually is mutable right? It changed the reference to an object to nothing. I defined a non-optional reference to an object which actually can point to nothing later on. That's why I am confused I need to mark an optional `unowned` reference as `var`, because even with `unowned let`, the reference was mutable already. – J. Doe Feb 24 '19 at 15:25
  • I can post some code snippets in another question if I am unclear – J. Doe Feb 24 '19 at 15:28
  • "When I mark an object as let unowned it is possible that the object is nil (the object has deallocated)." No. You are describing weak, not unowned. Unowned objects do not magically change to nil when the object is deallocated; that is, and always has been, a key difference between unowned and weak. – matt Feb 24 '19 at 15:28
  • That would be great if you think I haven't explained sufficiently here (note that I've expanded my answer). But please read the links I pointed you to first, because it sounds to me like you do not understand what unowned means (and has always meant). – matt Feb 24 '19 at 15:28
  • I am afraid that I am unable to understand something in the `Node` example, which is: Is there any difference if `var parent: Node?` declared as `weak` instead? Is it leads to the same result? Thanks in advance. – Ahmad F Feb 24 '19 at 15:52
  • 3
    @AhmadF It might work exactly the same way for _you_, but as I said in my answer, it leads to some possibly unwanted overhead, because you are making the runtime keep track of the weak reference in case it is deallocated. If we know that the parent can never be deallocated during the lifetime of the child, that is a waste of time and space and calculation complexities. Thus, as I said in my answer, unowned Optional lets you say what you mean and eliminate all of that complexity. – matt Feb 24 '19 at 16:13