7

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.

Verticon
  • 2,419
  • 16
  • 34

6 Answers6

4

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.

Vatsal Manot
  • 17,695
  • 9
  • 44
  • 80
  • Hi Vatsal. So then, why not use a strong reference? What is gained by making the reference unowned? – Verticon Dec 09 '16 at 13:25
  • 1
    @RobertVaessen that would create a **retain cycle** and thus leak memory. The customer instance would wait for the card instance to relinquish ownership of the customer instance, and the card instance would wait for the customer instance to relinquish ownership of the card instance. It's a bit of a mindf***. – Vatsal Manot Dec 09 '16 at 13:35
  • 1
    Saying the compiler “trusts” you mischaracterizes the compiler. The compiler guarantees that your program will crash immediately if you dereference an invalid `unowned` reference. The only time the compiler ”trusts” you (in the sense of assuming you know what you're doing and not generating safety checks) is when you use an object or function that has `unsafe` in the name. – rob mayoff Dec 09 '16 at 13:43
  • @robmayoff you're absolutely right. I was a little too liberal with my language. Have changed it to something more accurate. – Vatsal Manot Dec 09 '16 at 13:47
  • 1
    This is by far the best answer on this post. +1 – NSNoob Dec 09 '16 at 14:03
3

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
1

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.

Bob
  • 910
  • 1
  • 8
  • 12
  • Hi Bob. So, everything will work out okay if we have designed things such that only a single customer will ever hold a reference to a given credit card. That seems reasonable. Given that state of affairs: would the end result not be the same if the credit card had a strong reference to the customer? – Verticon Dec 09 '16 at 13:22
  • Thanks, Bob. I get it now. We can use unowned when the design of our code guarantees that its use will not result in accessing a nil reference. I.E. the design guarantees that when Customer is deallocated, CreditCard will also be deallocated. – Verticon Jan 03 '17 at 00:34
0

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.

Munahil
  • 2,381
  • 1
  • 14
  • 24
  • Hi Munahil. So, what is the practical difference of the credit card having an unowned reference to the Customer vs. having a strong reference? – Verticon Dec 09 '16 at 13:39
-1

Okay, I finally get it:

  1. The last reference to Customer (other than Credit Card's) is set to nil.
  2. ARC checks the Customer's reference count:
  3. Credit Card has a strong reference - Customer's reference count will be 1 so ARC will not deallocate it. Result - memory leak.
  4. 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

Verticon
  • 2,419
  • 16
  • 34
  • If something else retains CreditCard while Customer is being released, god forbids you ever touch that unowned pointer. – pronebird Dec 09 '16 at 14:06
  • Andy, Right your are. But, I think that the point here is that we have designed things such that what you say cannot happen and hence we have a situation where the use of unowned will work well for us. And, if we somehow violate our design then crashing is a good outcome. – Verticon Dec 09 '16 at 14:10
  • Robert, crash on weak `customer!` is somewhat clear and guaranteed. Crash on unowned pointer is a russian roulette. Memory, when released, is not being zeroed, side-effects to follow... If you're very careful and everything is by design, it's fine, but it's fine line to walk. – pronebird Dec 09 '16 at 14:14
  • Pretty sure people are just downvoting everything on this question. I mean the answer has -1... – SalvadorVayshun Dec 09 '16 at 14:49
-2

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

Community
  • 1
  • 1
SalvadorVayshun
  • 343
  • 1
  • 3
  • 19