2

I just read the ARC section in the Swift book and a few other related posts concerning weak and unowned references.

After my readings, I do have a clear understanding on what they are and in what situations each of them are to be used (see also this SO post which gives a great explanation of this).

However, I fail to understand why Apple even came up with these two solutions? Essentially, from a MM perspective, both come down to not creating a strong reference to the referred object (i.e. not increasing its retainCount). So, why even bother and provide two MM primitives here?

Now, developers need to understand when to use which of the two, and Apple did a great job in explaining the different scenarios, but they didn't say why. Wouldn't it have been simpler to e.g. only provide weak so that developers don't need to dig into the docs and understand the different use cases?

I guess, another way to phrase the question is, why at all should we use unowned, except for Apple telling us so? At least from a MM standpoint, this wouldn't make a difference and using weak where according to the docs we should use unowned wouldn't create a memory leak?!

Community
  • 1
  • 1
nburk
  • 22,409
  • 18
  • 87
  • 132
  • Is your question "why Apple even came up with these two solutions?" If so, this question is primarily opinion-based as only Apple employees can answer why the built the language like this. – JAL Feb 24 '16 at 15:53
  • @JAL ah no, sorry I guess I wasn't 100% clear in my question. Apple's docs make it seem that there is not actually a difference between `weak` and `unowned` except for their recommendation on when to use which. It seemed like the two were completely interchangeable from a MM perspective. They don't explicitly state that there are situations in which the compiler would actually complain about one but accept the other, so I was wondering about where these recommendations come from. – nburk Feb 24 '16 at 16:01

2 Answers2

3

The difference is in the optionality of variables. Like Apple says in the Unowned References section of the link you provided:

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

The usage of this is more visible in a closure block. Here you do not have to use ? operator or get a reference on the object if you use it inside the closure.

Instead of writing this:

UIView.animateWithDuration(0.2) {
    [weak self]
    () -> Void in
    self?.view.layoutIfNeeded()
}

However, if you can be sure that the reference to self will not be released before the animation and you can simply write unowned and do not have to use the ? operator or unwrap it with an if let statement:

UIView.animateWithDuration(0.2) {
    [unowned self]
    () -> Void in
    self.view.layoutIfNeeded()
}
Kádi
  • 2,796
  • 1
  • 16
  • 22
  • I'm pretty sure in your last sentence you meant "IFF you can be sure that the reference to self will not be released before the animation, you can simply write unowned.. ". If `self` actually _will_ be released before the closure executes, you would access a dangling pointer and the program would crash. – CouchDeveloper Feb 24 '16 at 17:27
  • 1
    Yes, you are right, I meant to write it and will fix it :) – Kádi Feb 24 '16 at 17:45
3

@Kádi's answer about weak variables being optional is correct, but incomplete.

Weak and unowned have a difference in meaning outside of Swift's Optional semantics. A weak reference is more accurately named an auto-zeroing weak reference. The system knows about an object stored in a weak variable, and when the object is deallocated, goes to the extra work to zero out the value. As a consequence of that, weak variables are optionals in Swift.

Unowned pointers are not memory managed at all. They are a raw memory pointer that can take any value. (They can still be typed to point to a particular type of structure, so they aren't always "raw" in the way a C void pointer is raw.) Unowned pointers are useful for pointing to malloc'ed memory, pointer arithmetic, and the like. Declaring a pointer type as unowned basically tells the compiler "Don't worry about it. I know what I'm doing." The burden is then on you to make sure the pointer is always valid, before you try to dereference it, and also manage the memory behind the pointer yourself.

Duncan C
  • 128,072
  • 22
  • 173
  • 272