Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dealloc uiviewcontroller/unload views on logout action

I think this is a pretty common usecase as I have seen it in several apps. But after spending couple of days, I am still struggling with this. I have a structure like the following:

UITabBarController
-- UINavigationController1
 ---- UITableViewController1

-- UINavigationController2
---- UITableViewController2

Now I have a logout button on UITableViewController2. When I click on that logout button I want all and any viewcontroller to be deallocated, all view unloaded. Basically start fresh like launching the app. I basically want the viewDidLoad on each of those UITableViewController called again.

I tried the following method to be called in my appdelegate when the logout action on UITableViewController2 is taken.

-(void) logout {
    for (UINavigationController* ctrl in self.tabBarController.viewControllers) {
        [ctrl popToRootViewControllerAnimated:NO];
        ctrl.visibleViewController.view = nil;
    }

[self.tabBarController.view removeFromSuperview];
[self.window addSubview:self.tabBarController.view];

}

But alas, it does not seem to work?

Any ideas how such a thing is accomplished? Also I see different behaviors in iOS4 vs iOS5 with the visibleViewController. I am not using any modal viewcontroller here. Any gotchas?

Update: I am not using ARC

thanks mbh

like image 720
mbh Avatar asked Jan 05 '12 18:01

mbh


2 Answers

Your for-loop will release and thus dealloc any view controllers that you have pushed onto the respective UINavigationController roots (depending on how many tabs you have), i.e. as these will not have a superview when you pop back to the root of each navigation controller, these are dealloc-ed automatically. These are your UITableViewControllers taken care of.

As for the respective UINavigationControllers, you would need your tabbar-controller to release the old instance. IMHO, this should be done for you when you release the UITabBarController.

This then leaves the UITabBarController itself. I don't think it can be done tbh. Your code will only remove the view, but not dealloc the tabbar controller itself. And as Krishna K points out, you need at least one view controller to reload all others. Putting the code into the appdelegate makes sense, but you need to ensure that your logout() will not cause a retain on the UITableViewController2 as well as the UITabbarController as it's called from UITableViewController2 somewhere.

One idea to explore, does your AppDelegate hold an instance to the TabBar-Controller which you could release and create a new instance after removing the view from self.window?

// manually create UITabBarController - AppDelegate holds instance
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    mytabcontroller=[[UITabBarController alloc] initWithNibName:@"foo" bundle:nil];
}

- (void) logout {
  [self.tabBarController.view removeFromSuperview];
  [mytabcontroller release];
  mytabcontroller=[[UITabBarController alloc] initWithNibName:@"foo" bundle:nil];
  [self.window addSubview:self.tabBarController.view];
}

But as I said, there might be caveats with memory management at this point.

like image 105
zero0cool Avatar answered Oct 12 '22 22:10

zero0cool


You need to release your view controllers. When their release method is called, that method should include statements to release all of its object's resources (and also dealloc its superclass).

like image 36
Jim Avatar answered Oct 12 '22 23:10

Jim