将在整个视图控制器多个presentViewController方法调用导致iOS中的内存泄漏?

我知道有很多与这个话题有关的讨论。 但在所有的讨论中,都与2个视图控制器(A&B)进行了讨论。 我的情况是相似的,但不同。

当有多个视图控制器如A,B,C,D时会发生什么。 所以呈现的stream程如同移动一样,

视图控制器A(主页)呈现视图控制器B(列表)。 然后从视图控制器B呈现视图控制器C(细节)。然后从视图控制器C呈现视图控制器D(高级细节)。 然后从视图控制器D呈现视图控制器A,以直接导航到家!

最好的做法是什么?

不知道你的项目结构和你将如何展示A,B,C,D,E,F然后从F返回到A的细节,我会大胆猜测,并说这可能导致内存泄漏,这取决于什么devise模式,你使用你的UIViewControllers。 正如@CaptJak在你的问题中所评论的那样,很难判断是否,何时以及何时会导致内存泄漏,特别是如果你使用委托模式在视图控制器周围传递数据。

就个人而言,当我做复杂的stream程,如呈现多个UIViewControllers,并发现自己需要回到几个屏幕,我不会popup堆栈上的意见,直到我想要的是在堆栈顶部(如果您使用导航控制器),如果视图控制器是以模态方式呈现,则closures视图控制器;如果我使用视图控制器,则展开视图。 这里的风险可能是视图控制器的内存可能已经释放。

我会评论,但我没有足够的声誉。 用一粒盐来回答我的问题,因为我在iOS开发中还是一个相当新鲜的东西。

编辑:感谢您的应用程序stream程中提供的详细信息。 既然你可以使用presentViewController,我假设你正在运行一个NavigationController? 如果是这种情况,我会使用popToViewControllerpopToRootViewController (如果A是你的根视图控制器),而不是再次从D呈现A. 如果A再次出现在D中,我猜测你的VC堆栈中会有2个A实例,这可能导致内存泄漏。

PopToViewController方法

 NSArray arrayOfVCs = self.navigationController.viewControllers; for(UIViewController *currentVC in arrayOfVCs) { if([currentVC isKindOfClass:[ViewControllerA class]) { [self.navigation.controller popToViewController:currentVC animated:YES] } } 

PopToRootViewController方法(假设A是导航控制器中的根视图)

 [self.navigationController popToRootViewControllerAnimated:YES] 

编辑2016年4月12日

我刚才一直在想这个问题,所以我实际上做了一个简短的RnD,只想在这里分享我的发现。 我做了一个粗糙的简单和肮脏的function,以获得我的非常简单的应用程序有史以来提出的所有模式视图控制器的堆栈。

我testing了A→B→C→B→C→B约20-30次。 每次我去B – > C的时候,内存增加了0.5MB(因为我的屏幕很简单,但是你可能会有所不同),最后从20+ MB增加到50+ MB。

在这个函数中,我logging了堆栈中呈现的视图控制器的数量,以及它们的名字。 到目前为止,它为我工作,但你可以试试看,看看它是否适合你。

 //global variables var vccount = 0 var vcnamelist = [String]() func getPresentingViewStackCount(currentVC : UIViewController!){ if(currentVC.presentingViewController != nil){ vccount = vccount + 1 let vc = currentVC.presentingViewController vcnamelist.append(NSStringFromClass((vc?.classForCoder)!)) getPresentingViewStackCount(vc) } } // to use func someRandomMethod(){ getPresentingViewStackCount(self) } 

尽pipe如此,仍然认为最好使用导航控制器。 这是他们的目的。 🙂

1.如果你这样expression,A-> B-> C-> D-> A,一个接一个,一个接一个,你会得到一个exception:

应用程序试图以模态方式呈现主动控制器

您无法呈现已经呈现的ViewController,就像您无法推送已位于UINavigationController堆栈中的ViewController一样。

2.如果您使用Storyboard构build应用程序,则可以使用unwind-segue从D跳回到A.

如果你使用代码来构build你的应用程序,你可以在D中保留A的弱引用,然后调用

 [A dismissViewControllerAnimated:YES completion:nil]; 

在ViewController D中作为dismissViewControllerAnimated让你回到A.

– (void)dismissViewControllerAnimated 🙁 BOOL)标志完成:(void(^ __nullable)(void))完成;
如果您连续呈现多个视图控制器,从而构build呈现的视图控制器堆栈,则在堆栈中较低视图控制器上调用此方法将取消其立即子视图控制器以及该堆栈上的该子视图之上的所有视图控制器。 当发生这种情况时,只有最顶层的观点才会以animation的方式被驳回。 任何中间视图控制器都可以简单地从堆栈中移除。 最顶层的视图使用其模式转换样式,这可能不同于其他视图控制器在栈中使用的样式。

我相信可以从UIButton(或者其他任何你用来控制你的stream程)的命令拖拽到你下一个想要呈现的视图控制器,以便正确导航。 然后,你放手,select你想要的任何演示方法,当你尝试它,它应该工作。 我假设你使用XCode这个,我不知道其他的开发应用程序。

这是为了防止发生内存泄漏,但请注意,您将不得不为每个单独的视图控制器创build单独的文件。 其他手动forms的切换可能导致内存泄漏,这取决于您的情况的内容。

没关系,如果你将显示新创build的视图控制器。