我有一个iPad应用程序,它有很多屏幕和很多segue选项。 目前,我只是使用performSegueWithIdentifier来启动这些segue,我担心的是,当用户执行越来越多的segues时,我占用了大量内存。 我见过人们推荐使用函数popToRootViewControllerAnimated:如果使用UINavigationController,但问题是我没有使用它。 如何阻止VC的数量激增? 应用程序的工作方式,用户不断返回到根VC - 实际上是一个搜索屏幕。因此,如果我需要在需要这样一个segue时清除VC的堆栈,那我认为这将解决我的问题,但我不知道如何解决这个问题。 感谢您的任何建议。
答案 0 :(得分:10)
当您使用segues时,流程会向后和向前移动。当用户向后移动(即按下“后退”)时,它将不会推送到新的VC,但它将弹出到已存在的VC。弹出时,当前VC将从堆栈和内存中删除。
如果你在流程中有向后移动的segues,那么这是错误的。你只需要segues继续前进。
正确的SEGUE准备
在准备segue时,你永远不应该创建自己的视图控制器并推送它们。故事板可以为您完成所有这些。
正确的prepareForSegue方法看起来应该是这样的......
- (void)prepareForSegue:(UIStoryBoardSegue*)segue
{
if([segue.identifier isEqualToString:"SomeSegue"])
{
MyNewViewController *controller = segue.destinationViewController;
controller.someProperty = "some value to pass in";
}
}
这就是你所需要的一切。请注意,如果您打算将某些信息传递给新的视图控制器,则只需要此选项。如果你没有向前传递任何东西,那么你根本就不需要这种方法。
当方法结束时,新的VC将被故事板文件推送到屏幕上。
UNWIND SEGUES
如果您有随机流(如评论中所示),那么您可以使用展开segues来实现此目的。
在你'A'视图控制器中有一个类似......的功能
- (IBAction)someUnwindAction:(UIStoryboardSegue*)sender
{
//some action to run when unwinding.
}
它需要接收UIStoryboardSegue对象。如果设置为IBAction,您也可以从Interface Builder访问它。
现在,当你想要去A> B> C> B>然后只使用了标准的推送和弹出(来自segue和后退按钮)。
当你想要去A> B> C>那么你可以使用来自控制器C的展开segue。
如果你有一个取消按钮或控制器C中的某个东西,这是在界面生成器中,这应该会带你回到控制器A.然后在控制器C下面的界面生成器中,你将有一个带有门的绿色小方块指出它的箭头。只需将取消按钮的操作指向此符号,然后选择“someUnwindAction”即可。 (注意,unwindAction在A中,按钮在C中。)然后XCode使用它来弹回你一直回到A并处理删除任何内存和东西。如果您愿意,也可以将其他信息发回给A.
如果您想以编程方式从C访问此展开segue,那么您可以运行...
[self performSegueWithIdentifier:"someUnwindAction" sender:nil];
这也将弹回A。
答案 1 :(得分:1)
imho我没有看到使用segue的任何问题,它比其他任何事情都简单得多。如果您担心消耗的内存,那么只需分析您的应用程序,看看它吃多少以及调用“内存压力处理程序”的频率。
答案 2 :(得分:0)
好的,我相信我已经弄明白了。它似乎有用。
由于我一直回到常见的VC,我将代码放在我想要回到这个'root'VC的地方以清除VC堆栈。
我仍在我的普通代码中执行实际的segue
[self performSegueWithIdentifier:@"editBackToSearch" sender:self];
然而,在'prepareForSegue:'方法中,我不再创建新的VC对象,而是执行任何我未完成的工作(保存我的数据),然后使用以下代码清除VC堆栈。
UIViewController *vc = self;
while ([vc presentingViewController] != NULL)
{
vc = [vc presentingViewController];
}
[vc dismissViewControllerAnimated:NO completion:nil];
它似乎运行顺畅,并具有释放这些VC吸收的内存所需的影响(通过分析器确认)。
最后一条评论 - 出于某种原因,我无法为解雇命令设置动画,这似乎触发了无限循环并导致了EXC_BAD_ACCESS。将动画设置为NO,虽然效果很好。
感谢您的帮助。
答案 3 :(得分:0)
Swift 3 :这是为了防止Swift 3和4中的内存泄漏
@IBAction func entryViewSelected(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}