3

I have a class MasterViewController that loads on app startup. Inside viewDidLoad() it checks if a user is logged in, and presents one view controller or another based on the outcome. If you aren't logged in and then proceed to do so, the app loads up a new MasterViewController. My goal is to essentially replace the existing MasterViewController with a new instance so it performs the check in viewDidLoad once again. I've tried the following, and they both work:

// changing the root view controller
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
appDelegate.window!.rootViewController = MasterViewController()
appDelegate.window!.makeKeyAndVisible()

// using presentViewControllerAnimated
someViewController.presentViewControllerAnimated(MasterViewController(), animated: true, completion: nil)

...but while presentViewControllerAnimated has a nice animation, changing root doesn't. More importantly, changing the root view controller doesn't destroy the existing one (at least deinit is never called..), and obviously presentViewControllerAnimated doesn't do that either, so in both cases I have this view controller floating around that I don't want anymore.

I can just imagine some scenario where a user logs out and back in repeatedly and suddenly I have 10 MasterViewControllers on top of one another. Any way to completely purge a view controller? Or is this just totally unnecessary?

EDIT

Just remembered presentViewControllerAnimated is for presenting a vc modally, so that's definitely not what I want. Would be nice to change the root view controller with a similar animation though. All the animations I've seen with root vc changes were pretty wonky.

Nischal Hada
  • 3,230
  • 3
  • 27
  • 57
Ryan Bobrowski
  • 2,641
  • 3
  • 31
  • 52
  • 1
    usually you shouldn't worry about instances of your `MasterViewController` loitering around when you reset the `UIWindow`'s `rootViewController`... iOS' memory management system takes care of the instances for you and destroys them when appropriate. – nburk Jun 06 '15 at 06:15

2 Answers2

1

The following Stackoverflow thread touches on your concern about the old UIViewController sticking around in memory:

Stackoverflow: Changing root view controller of a iOS Window

serge-k's answer comes from the UIWindow Class Reference:

var rootViewController: UIViewController?

The root view controller for the window.

The root view controller provides the content view of the window. Assigning a view controller to this property (either programmatically or using Interface Builder) installs the view controller’s view as the content view of the window. If the window has an existing view hierarchy, the old views are removed before the new ones are installed. The default value of this property is nil.

The Resource Management in UIViewController section of the UIViewController Programming Guide also contains a note on this:

The default behavior for a view controller is to load its view hierarchy when the view property is first accessed and thereafter keep it in memory until the view controller is disposed of. The memory used by a view to draw itself onscreen is potentially quite large. However, the system automatically releases these expensive resources when the view is not attached to a window. The remaining memory used by most views is small enough that it is not worth it for the system to automatically purge and recreate the view hierarchy.

You can explicitly release the view hierarchy if that additional memory is necessary for your app. Listing 4-3 overrides the didReceiveMemoryWarning method to accomplish this. First, is calls the superclass’s implementation to get any required default behavior. Then, it cleans up the view controller’s resources. Finally, it tests to see if the view controller’s view is not onscreen. If the view is associated with a window, then it cleans up any of the view controller’s strong references to the view and its subviews. If the views stored data that needs to be recreated, the implementation of this method should save that data before releasing any of the references to those views.

Community
  • 1
  • 1
borwahs
  • 26
  • 4
0

Following code and concept is helpful for you

  var window: UIWindow?
  var viewController: MasterViewController?
  var navigationVC:UINavigationController?
  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
  {
    window = UIWindow(frame: UIScreen.mainScreen().bounds)
    if let window = window {
        window.backgroundColor = UIColor.whiteColor()
        viewController = MasterViewController(nibName: "MasterViewController", bundle: nil);
        //If you want NavigtionController
        navigationVC = UINavigationController(rootViewController: viewController!)
        navigationVC?.navigationBar.hidden = true
        window.rootViewController = navigationVC
        //Or If you don't want navigation controller
        window.rootViewController = viewController
        window.makeKeyAndVisible()
    }
    return true
}

Here

 1.The root view controller provides the content view of the window. Assigning a view controller to this property (either programmatically or using Interface Builder) installs the view controller’s view as the content view of the window. 
 2.If the window has an existing view hierarchy, the old views are removed before the new ones are installed.
 3.The default value of this property is nil.
user3182143
  • 9,459
  • 3
  • 32
  • 39