如何在注销操作中释放UIViewController/卸载视图

6

我认为这是一个非常常见的用例,因为我在几个应用程序中看到过。但是经过几天的努力,我仍然在努力解决这个问题。我有以下结构:

UITabBarController
-- UINavigationController1
 ---- UITableViewController1

-- UINavigationController2
---- UITableViewController2

现在我在UITableViewController2上有一个注销按钮。当我点击该注销按钮时,我希望所有的视图控制器都被解除分配,所有的视图卸载。基本上像启动应用程序一样重新开始。我希望每个UITableViewController的viewDidLoad再次被调用。

我尝试了以下方法,在UITableViewController2上采取注销操作时在我的AppDelegate中调用:

-(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];

不过很遗憾,似乎它不起作用了?

有什么想法可以实现这样的事情吗?我在visibleViewController中看到iOS4和iOS5有不同的行为。我这里没有使用任何模态视图控制器。有什么需要注意的地方吗?

更新:我没有使用ARC。

谢谢 mbh


我不确定这对你的情况是否完全适用,但当注销时我只是想在popToRootViewController中执行,此时我真的很喜欢Adam Kemp的想法,他建议你添加一个NSNotificationCenter事件用于捕获UserDidLogOut,并在你的视图控制器中处理该事件。 - Nick Merrill
3个回答

2

你的for循环将释放并销毁任何已推送到各自UINavigationController根视图上的视图控制器(取决于你有多少个选项卡),即当你弹回到每个导航控制器的根时,这些视图控制器将没有父视图,因此会自动被销毁。这样你的UITableViewControllers就被处理了。

至于各自的UINavigationControllers,你需要让tabbar-controller释放旧实例。在我看来,当你释放UITabBarController时,应该为你完成这个操作。

这就留下了UITabBarController本身。我不认为它能够做到。你的代码只会移除视图,但不会销毁tabbar控制器本身。正如Krishna K所指出的,你需要至少一个视图控制器重新加载所有其他视图控制器。 将代码放入appdelegate中是有意义的,但你需要确保你的logout()不会在某个地方调用UITableViewController2时对其以及UITabbarController进行保留。

一个值得探索的想法是,你的AppDelegate是否持有TabBar-Controller的实例,你可以在从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];
}

但正如我所说,这一点可能存在内存管理方面的注意事项。


1
你需要释放你的视图控制器。当它们的释放方法被调用时,该方法应包括释放所有对象资源的语句(并且也要dealloc其超类)。

我该如何实现这个?[ctrl.visibleViewController release]?不起作用。[ctrl release]?我也试过了。 - mbh
你正在使用ARC吗?如果是,答案可能会有所不同。 - Jim
谢谢指出。我应该提到的。已经更新问题,说明我没有使用ARC。 - mbh
在这种情况下,我建议您查看每个类,在其中分配和保留视图控制器(或任何其他对象),并确保在dealloc方法中有相应的释放。您可能希望将对象引用ivars,以便在分配它们的位置和dealloc方法中引用它们。按名称单独释放它们。使用断点验证正在执行释放操作,并调用相应的dealloc。如果未调用dealloc,则可能已在其他位置保留它。如果是这样,请在这些其他位置释放它。 - Jim

1

你的两个导航控制器的 rootViewController 分别是它们的 TableView 控制器。所以我认为 popToRootViewController 不会起作用。

你可能需要重置数据和刷新视图,而不是释放视图。


我有多个tableViewControllers。因此,我使用了UINavigationController。所以Pop帮助dealloc除了根/顶部之外的所有其他视图控制器。我遇到的问题是无法dealloc。 - mbh
你可以释放除根视图控制器外的所有视图控制器,因为你至少想要一个视图控制器来重新加载所有其他控制器。 - Krishna K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接