Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is self deallocated while dismissing view controller

I have a question regarding memory deallocation and blocks/closures.

Following is the Swift method

    self!.dismissViewControllerAnimated(false, completion: {
        println(self);
     })

Or the objective C method

   [self dismissViewControllerAnimated:NO completion:^{
       NSLog("%@",self);
   }];

I would really appreciate if anyone could explain when in the above method self would be deallocated . Is it after the completion block is run or before that? I understand its taken care by ARC but I would like to know if self gets release message in the completion block or after that. Hence, if I do some minor clean up in the completion block (accessing self), is that safe/acceptable or not?

like image 775
Vik Singh Avatar asked Jul 23 '14 00:07

Vik Singh


People also ask

How do you dismiss the presenting view controller?

When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it.

How do I remove Viewcontroller from memory?

You can't remove a view controller from within itself (i.e. viewDidDisappear) - what you need to do is to remove all references to it, at which point ARC will deallocate it.


2 Answers

There are really two separate questions to understand the answer completely:

1. When Are Variables Referenced Inside of Closures Released?

You can think of a closures as just another type (in Swift they really are). Every closure creates a strong ownership over the variables referenced inside of it, including self. This ensures that you never reference a variable that has been deallocated. Just like in any other object, when the closure gets deallocated, it releases its ownership over all of its variables.

If the closure is the only thing with a strong reference to that a variable, the variable will be dealloced when the closure is dealloced.

So in short, variables stay in memory as long as the closure is still in memory.

2. When Are Closures Deallocated?

Now the second part of this that is important to understand, is when does a closure get dealloced. You could store a closure in a variable:

func myMethod() {
    var myClosure = {
        println(self)
    }
    myClosure()
}

In this case, the closure has a strong reference from its variable myClosure and the closure has a strong reference to self. As soon as myClosure goes out of scope, i.e. when myMethod exits, it will be dealloced. When that happens, self will be released.

You may also have a situation, like in your question, where you are passing a closure into another method. In this case, the method you are passing the closure into is capturing a strong reference to your closure. When that method exits, it will release your closure, the closure will be deallocated, and it will release all variables captured inside it.

The Exception

Sometimes it is necessary to define a closure that does not take ownership over a variable. You would do this to avoid circular references. You can read more in Apple's documentation on what a circular reference is and how to prevent them here. However, it is important to realize that unless you put in explicit effort (and code), closures will always capture strong references to variables referenced inside of it.

like image 111
drewag Avatar answered Oct 27 '22 01:10

drewag


In Swift, while developing/debugging and trying to understand the timing of operations, you can add the following to your View Controllers (or any class), to track if or when the instance is a about to deallocated.

Although that won't help you detect 'strong reference cycles' described here:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

deinit {
    println(__FUNCTION__, "\(self)")
}
like image 25
clearlight Avatar answered Oct 27 '22 00:10

clearlight