Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I ever use unowned self?

Tags:

ios

swift

swift3

The following pattern happens a lot in iOS apps:

class MyViewController: UIViewController {
    let myModel = MyModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        myModel.foo() { [***] in
            // use self here
        }
    }
}

class MyModel {
    public func foo(complete: () -> Void) {
        // do something
        complete()
    }
}

The consensus is to use either [unowned self] or [weak self] in place of the [***], unowned when you can guarantee that self will not be nil at the time of completion and weak when you're not sure the reference will still be valid.
What I don't understand is why I would ever risk using unowned, maybe I'm sure that right now the reference will never be nil, but that can change in the future. I could also have overlooked an edge-case, mistakes happen. I could just as easily always use weak, and put a guard at the top of the closure to be able to use self without a ! or ?.
What is the use of unowned? Is it faster than weak+guard? Is it syntactic sugar? It seems to go against Swift's philosophy of protecting the developer against common mistakes that can cause crashes.

like image 516
kevin Avatar asked Sep 25 '17 14:09

kevin


People also ask

Why do we use unowned and weak self?

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 general, be very careful when using unowned.

Where unowned must be used?

When to use unowned self or weak self. The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle.

Why can not we just use weak everywhere and forget about unowned?

Without using weak or unowned you're basically telling ARC that a certain “strong reference” is needed and you're preventing the reference count from going to zero. Without correctly using these keywords we possibly retain memory which can cause memory leaks in your app.

Do we need weak self?

Using [weak self] is only required within situations in which capturing self strongly would end up causing a retain cycle, for example when self is being captured within a closure that's also ultimately retained by that same object.


2 Answers

unowned has a marginal performance advantage over weak because the runtime doesn't have to keep track of the reference to turn it into nil when the object goes away.

In respect of retain cycles (well, strong reference cycles), neither weak nor unowned creates a strong reference (in pre ARC terms, neither increments the retain count) so there is no danger of a reference cycle, in fact, that is why you need to specify weak or unowned for self in closures.

Also, with unowned you can use the reference as a non optional, so you don't have to put any code in the closure to unwrap it.

I always use weak unless there is a really good performance reason not to.

NB in your code, I do not think either is necessary because the closure is not escaping i.e. The reference to it taken in the function call foo does not persist after the end of foo's scope.

like image 118
JeremyP Avatar answered Oct 11 '22 22:10

JeremyP


I believe that using unowned adds to the risk than using weak self. Mistakes do happen and one example of it would be starting an API call in a view controller, let it wait for the response to arrive and suddenly popping that view controller may cause it to get deallocated (If there are no strong references to it). By the time when the response arrives, our view controller object would be gone, and our app will crash on our face. It is up to us to decide which one to use in which place.

As Jeremy pointed out, unowned does not have the responsibility to keep track of the reference count, so it has ever so slight performance advantage over strong and weak.

like image 40
badhanganesh Avatar answered Oct 11 '22 22:10

badhanganesh