2

I encountered this issue on a larger Swift project, but was able to replicate it with a very basic project. I have the following view controller class:

class ViewController: UIViewController {
    deinit {
        println("Deinitializing")
    }
    
    override func viewDidAppear(animated: Bool) {
        NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "segue", userInfo: nil, repeats: false)
    }

    func segue() {
        self.performSegueWithIdentifier("segue", sender: self)
    }
}

My storyboard is configured so there are two view controllers, both using the above class and with Show Detail segues pointing to one another. I can confirm that they "bounce" back and forth. Despite a new instance being shown every time, and no retain cycles, the previously displayed view controller's deinit method is not called.

I've been able to get my desired behaviour through the use of a custom segue, but my question is: Is this behaviour expected?

The documentation seems to indicate that it should work how I expect it, I've highlighted the part that I think applies to my test project.

Source

Present the content in the detail area. If the app is displaying a master and detail view, the new content replaces the current detail. If the app is only displaying the master or the detail, the content replaces the top of the current view controller stack.

I would have expected that replacing the top of the current view controller stack would cause the current view controller to be deinitialized.

Alternative to Show Detail

For reference, I was able to achieve my desired behaviour through this segue (which doesn't do anything fancy, and may be incorrect):

class ExampleSegue: UIStoryboardSegue {
    override func perform() {
        let source = self.sourceViewController as UIViewController
        let destination = self.destinationViewController as UIViewController
        
        source.view.window?.rootViewController = destination
    }
}

Thank you for any assistance!

Community
  • 1
  • 1
Arkcann
  • 618
  • 7
  • 15
  • Do you use navigation controller? I think when you show the second view controller, the first view controller will be push to a stack which is a property of navigation controller. So... it does not deinit. – Nhut Duong Jan 13 '15 at 03:53

1 Answers1

4

If you're not using a navigation controller or a split view controller, then a "Show Detail" segue is the same as a modal presentation. A controller that presents another keeps a reference to it in its presentedViewController property (and the presented controller has a reference to the presenter in its presentingViewController property). Thus, none of the controllers will ever be deallocated. If you want to go back to the previous controller, you should either use an unwind segue or use dismissViewControllerAnimated:completion in code.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • 1
    Do you possibly have a reference to where you found that a "Show Detail" segue acts as a modal presentation when no navigation controller is provided? I'm sure you're correct, since that matches the behaviour I'm seeing, but I'd love to read more about it. Edit: I also think my initial confusion arose from Apple's decision to display that segue as "Show Detail (e.g. Replace)" in Interface Builder, in my mind replace != modal – Arkcann Jan 13 '15 at 15:20
  • @Arkcann, I don't know if there is any reference. I did some experiments, and found that the segue behaved like a modal (cover vertical animation), and that the presentedViewController and presentingViewController properties were non-nil after the segue. – rdelmar Jan 13 '15 at 16:38