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 动画 [重复]
在tableView中打开特定的viewController
iPhone - 设计我自己的 viewController 过渡