iPhone - 删除整个 viewController,而不仅仅是它的视图

Posted

技术标签:

【中文标题】iPhone - 删除整个 viewController,而不仅仅是它的视图【英文标题】:iPhone - removing an entire viewController, not just its view 【发布时间】:2014-04-12 21:38:32 【问题描述】:

我没有使用导航控制器或标签栏控制器,我没有使用推送/弹出方法或模态显示视图。在我的主视图控制器中,我添加了一个视图控制器,如下所示:

UIViewController *nextController;
nextController = [[GamePlayViewController alloc] initWithNibName:@"GamePlayView" bundle:nil];
[nextController performSelector:@selector(setDelegate:) withObject:self];

temporaryController = nextController;

[self.view addSubview:nextController.view];

这个视图控制器遵循一个委托协议,当用户在这个游戏视图中结束时,这个代码被调用:

[delegate backToMenu:self];

在应用的主视图控制器中调用这个函数:

- (void)backToMenu:(GamePlayViewController *)sender 
    NSLog(@"back to menu");

    [temporaryController.view removeFromSuperview];

使用 removeFromSuperview 删除视图似乎只是摆脱了视图,但由于 NSLogging,我可以看到代码仍在该已删除视图的 .m 文件中执行。该视图仍在应用程序的内存中。它并没有像我希望的那样被丢弃。

“Release”是一个永远不会与 ARC 一起使用的旧遗物,那么如何才能完全删除使用 alloc/initWithNibName 创建的 viewController?

谢谢!

【问题讨论】:

temporaryController 是如何定义的?如果它是一个强属性,答案可能就像将其设置为 nil 一样简单。 @PhillipMills 它在我的主视图控制器的头文件中声明: UIViewController *temporaryController;作为 Rich 下面提供的解决方案的一部分,尝试将其设置为 nil,但并未更改该视图仍继续运行代码的方式 【参考方案1】:

您还应该使用视图控制器生命周期方法。

添加:

GamePlayViewController *nextController = [[GamePlayViewController alloc] initWithNibName:@"GamePlayView" bundle:nil];
nextController.delegate = self;
[self addChildViewController:nextController];
[self.view addSubview:nextController.view];
[nextController didMoveToParentViewController:self];

temporaryController = nextController;

删除:

[temporaryController didMoveToParentViewController:nil];
[temporaryController.view removeFromSuperview];
[temporaryController removeFromParentViewController];
temporaryController = nil;

另外,如果temporaryController 是一个强属性(或者您使用了 iVar),您应该在删除它之后将其 nil 删除。

由于CAAnimation 保留其委托,因此您需要移除动画并将nil 移除委托。

-(void)didMoveToParentViewController:(UIViewController *)parentViewController

    [super didMoveToParentViewController:parentViewController];

    if (!parentViewController) 
        CAAnimation *animation = [movingObject.layer animationForKey:@"animatePositionX"];
        animation.delegate = nil;
        [movingObject.layer removeAnimationForKey:@"animatePositionX"];
    

如果你想检查你的视图控制器是否被解除涂层,你应该实现dealloc 方法并在其中放置一个断点。我建议在 NSLog 上设置一个断点,因为我不知道你已经注销了多少,所以它可能会被遗漏,断点很明显 - 实际上停止了程序流程。

【讨论】:

@ObjectiveFlash 我已经更新了针对您的问题在代码中添加更多上下文。 感谢您抽出宝贵时间回答我。在将代码更改为您在此处显示的内容后,我仍然会在已删除FromSuperview 和removedFromParentViewController 并设置为nil 的viewController 上执行代码。不知何故,尽管 viewController 的视图消失了,但它仍然处于活动状态。 CAAnimation 及其子类 CABasicAnimation 按照 documentation 保留他们的代表,这就是为什么它没有被释放,我会用一些代码更新我的答案。 @ObjectiveFlash,你的测试是问题所在。使用 performSelector:withObject:afterDelay: 防止控制器被释放! @ObjectiveFlash, performSelector:withObject:afterDelay: 设置一个计时器,并且计时器保持对其目标(将是您的控制器)的强引用,这就是您的控制器永远不会被释放的原因。不要使用它来检查您的控制器是否还活着,只需实现 dealloc,并在其中放置一个日志。我想你会发现这个答案中的代码会导致你的控制器被释放。

以上是关于iPhone - 删除整个 viewController,而不仅仅是它的视图的主要内容,如果未能解决你的问题,请参考以下文章

像 Facebook Iphone 应用程序一样滑动 ViewController 动画 [重复]

iphone基本发布问题

在tableView中打开特定的viewController

iPhone - 设计我自己的 viewController 过渡

iPad SplitViewController - 使用 iPhone 故事板 ViewController

iPhone - 如何制作 viewControllers 风景?