25

When my app first loads, I set the rootViewController property of my UIWindow to controllerA.

Sometime during my app, I choose to change the rootViewController to controllerB.

The issue is that sometimes when I do a flip transition in controllerB, I see controllerA's view behind it. For some reason that view isn't getting removed. Whats even more worrying is that after setting the rootViewController to controllerB, controllerA's dealloc method never gets fired.

I've tried removing the subviews of UIWindow manually before switching to controllerB, that solves the issue of seeing controllerA's views in the background but controllerA's dealloc still never gets called. Whats going on here????

Apples docs say:

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.

UPDATE

Here's the code of my AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self showControllerA];
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)showControllerA
{
    ControllerA* a = [ControllerA new];
    self.window.rootViewController = a;
}

- (void) showControllerB {
    ControllerB* b = [ControllerB new];
    self.window.rootViewController = b;
}
aloo
  • 5,331
  • 7
  • 55
  • 94
  • Can you provide the code for your `application:didFinishLaunchingWithOptions:` method in your app delegate? – Cezar Jul 13 '13 at 17:06
  • Stupid question, but do you set the `controllerA` to nil when you push the second controller? If not then it will not dealloc. (I'm assuming you are) – Putz1103 Jul 13 '13 at 22:41
  • I never keep a pointer to controllerA so not sure what I would set to nil. – aloo Jul 14 '13 at 01:02
  • 1
    @Cezar just updated the question with a condensed version of my app delegate code – aloo Jul 14 '13 at 01:06

5 Answers5

10

It turns out there are two separate issues. 1) I had a retain cycle in Controller A so it was never getting dealloc'd. Secondly, in order to change the root view controller you must remove the windows subviews first (even though the docs suggest otherwise)

aloo
  • 5,331
  • 7
  • 55
  • 94
1

The problem could be in your implementation of ControllerA or ControllerB, they may retain 'self' in the code so ARC cant automatically dealloc you ViewController. Can you post you ControllerA and ControllerB implementation.

ntus1017
  • 11
  • 1
  • 2
  • That would explain why dealloc isn't getting called. But why would the view from controllerA still be visible behind controllerB. Doesn't changing the root view controller remove controllerA's views from the window? – aloo Jul 14 '13 at 02:09
0
var loginNavigationController: OnBoardViewController?{
    willSet{
        if newValue == nil {
            loginNavigationController?.view.removeFromSuperview()
        }
    }
}

loginNavigationController = nil

Ankish Jain
  • 11,305
  • 5
  • 36
  • 34
0

It's apple's bug, we assume ViewControllerA as the current rootViewController:

// ViewControllerA.m
- (void)buttonClick {
    [self dismissViewControllerAnimated:YES completion:^{
        // [((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // OK
    }];

    [((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // ViewControllerA's view will not dealloc 
}

// AppDelegate.m
- (void)resetRoot {
    ViewControllerB *controller = [[ViewControllerB alloc] init];
    self.window.rootViewController = controller;
}

If reset window's rootViewController as this code, the ViewControllerA's view will never dealloc.

0

An even simpler solution is to set the backgroundColor of your new window to .white or any color. The default is nil, which results in a transparent background. That is why the older window (on top of which the new one is made visible) is being seen through.

hoshy
  • 481
  • 6
  • 15