【问题标题】:iPhone - removing an entire viewController, not just its viewiPhone - 删除整个 viewController,而不仅仅是它的视图
【发布时间】: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,但并未更改该视图仍继续运行代码的方式

标签: ios iphone objective-c uiviewcontroller


【解决方案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,并在其中放置一个日志。我想你会发现这个答案中的代码会导致你的控制器被释放。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 2023-03-06
  • 2013-03-05
相关资源
最近更新 更多