What is the difference between a weak reference and an unowned reference?
P

8

264

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++?

Phosphoresce answered 3/6, 2014 at 9:27 Comment(6)
Very good article on andrewcbancroft.com/2015/05/08/…Mousetail
My experience is to use unowned for the classes we control, for Apple classes, use weak because we can't guarantee for sure what it doesCrossfertilization
@NoorAli, or "ownedBy" as the "unowned" reference often points to the owner.Phosphoresce
NOTE: There are important performance implications to be aware of with each of these references: #58635803Voorhis
@EpicByte Sometimes a full GC like Java or C# is worth the overhead.Phosphoresce
@EpicByte #34843624 this states other wiseOnfroi
J
385

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.

Jaredjarek answered 24/9, 2014 at 19:43 Comment(10)
This is somewhat trivial but I find the example of the Apartment and Person somewhat confusing which also presents an additional solution to break the strong reference cycle. A person's apartment is optional and therefore can be nil as well as an Apartment's tenant is optional and therefore can be nil so both properties can be defined as weak. ```Christianachristiane
class Person { let name: String init(name: String) { self.name = name } weak var apartment: Apartment? } class Apartment { let number: Int init(number: Int) { self.number = number } weak var tenant: Person? }Christianachristiane
What's the difference between weak var Person? vs. var Person? ?Entrance
@JustinLevi, If you declare both properties as weak, there is a possibility for them to be deallocated. The Person keeps a strong reference to the Apartment so the Apartment will not be deallocated. If the apartment would have the same strong reference toward the Person, they would create a retain cycle - which can be broken by the programmer at runtime if he knows about it, but otherwise it's just a memory leak. This is all the fuss about strong, weak and unowned: memory management at a higher level, because ARC does all the dirty stuff for us. Avoiding retain cycles is our job.Jaredjarek
@Dean #11014087Jaredjarek
@Ilea Cristian Is the lifetime of weak greater than unowned or it's the other way round?Compromise
why is it called "unowned" thoughConstance
Are the only benefit of unowned over weak is that you don't need to unwrap and can use a constant? Is there any instance where you couldn't use weak and could only use unowned?Millepore
@Compromise The object that has an unowned reference to a property, it is alway valid. weak properties can be nil at anytime. So I guess you can say unowned reference has a more guaranteed lifetime.Millepore
So is weak! the same as unowned, apart from weak needing to be a variable?Whitesell
P
37

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

Pyknic answered 21/10, 2014 at 17:47 Comment(3)
your Q2 example program simple to understand about unowned..thanks.. can you add same type of example for weak & strong..Kuehn
Can you include a common example for unowned or weak?Multiversity
Consider objects parent & child, if child can't exist without a parent then use unowned for the property of parent in child class. weak is vise versa. Nice explanation @myxtic ! unowned references are just weak references that are guaranteed to have a value !Labio
R
27

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

Roundish answered 27/10, 2014 at 23:37 Comment(7)
Why not just use weak even if self can never be nil, no harm done right?Combs
hi @Combs - that is indeed the critical question.Elegist
[weak self] => If I use closure inside viewDidLoad(), how can self be nil?Bootery
@HassanTareq, I think couple of good examples are referred in the article, mentioned above. Check "Resolving Strong Reference Cycles for Closures" section, esp. Quote: " 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.” Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).” iBooks. itunes.apple.com/de/book/the-swift-programming-language-swift-4/…"Coadunate
@HassanTareq by the time the closure executes, which may be long in the future (http request for instance), the user might have already dismissed the view controller. If you use unowned in this case you'll crash the app.Equilibrate
@Combs If you always use weak, the compiler will force to check for optional before use. In case you did not put that check, it will give compile time error. There is no other Harm.Taproot
@Combs If you use weak, the variable will be optional so you need to safely unwrap it every time. By using unowned, you can avoid making the variable optional so unwrapping. Also you are giving a hand to the compiler by assuring that this variable never going to be nil.Thickness
M
6

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.
Machree answered 21/5, 2015 at 16:38 Comment(0)
C
2

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.

Carlos answered 5/10, 2019 at 15:41 Comment(0)
P
0

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
    }
}
Pish answered 6/6, 2014 at 19:35 Comment(1)
link to wwdc video or title ?Putup
J
-1

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.

Jenjena answered 26/12, 2018 at 19:39 Comment(0)
B
-1

The main difference is between Weak and Unowned is Optional

I share an example below for Weak

 class Apartment {
    let unit: String
    weak var tenant: Person?
    
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }
    
    deinit {
        print("Apartment \(unit) is being deallocated")
    }
}

class Person {
    let name: String
    
    init(name: String) {
        self.name = name
        print("Person \(name) is being initialized")
    }
    
    var apartment: Apartment?
    
    deinit {
        print("Person \(name) is being deallocated")
    }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")

john?.apartment = unit4A
unit4A?.tenant = john

john = nil // Person John is deallocated
unit4A = nil // Apartment 4A is deallocated

Here I used weak for:

  • The weak reference is declared as an optional (Person?) because the Apartment class does not necessarily require a tenant.
  • An apartment may be vacant, meaning it doesn't have a tenant assigned to it. Therefore, the reference to the tenant is optional, as there might not be a tenant associated with the apartment.

I share an example below for Unowned

 class Customer {
    let name: String
    var creditCard: CreditCard?
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) is being deallocated")
    }
}

class CreditCard {
    let number: String
    unowned let owner: Customer
    
    init(number: String, owner: Customer) {
        self.number = number
        self.owner = owner
    }
    
    deinit {
        print("Credit card \(number) is being deallocated")
    }
}

var john: Customer? = Customer(name: "John")
john?.creditCard = CreditCard(number: "1234567890123456", owner: john!)

john = nil // Both Customer and CreditCard instances will be deallocated
  • The unowned reference is declared as non-optional (Customer) because the CreditCard class requires an owner.

  • A credit card must have an owner; it cannot exist without one. Therefore, the reference to the owner is declared as non-optional, using unowned.

  • Using unowned in this scenario asserts that the CreditCard instance will always have an associated Customer instance, as it's a necessary requirement for the existence of a credit card.

In summary, the choice between using an optional weak reference and a non-optional unowned reference depends on the nature of the relationship between the objects and whether the referenced object is essential for the existence of the referring object. If the referenced object is optional or may be absent, use weak. If the referenced object is required and its absence would indicate a logical error, use unowned.

Benighted answered 25/3, 2024 at 8:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.