为啥 ARC 在 popViewController 之后不释放内存

Posted

技术标签:

【中文标题】为啥 ARC 在 popViewController 之后不释放内存【英文标题】:Why ARC is not deallocating memory after popViewController为什么 ARC 在 popViewController 之后不释放内存 【发布时间】:2014-02-19 08:36:11 【问题描述】:

我正在 UINavigationController 中推送和弹出 ViewController。

我正在跟踪我的应用程序的内存消耗。 在推送新的 viewController 时,内存消耗逐渐增加,但是当我使用 [self.navigationController popViewControllerAnimated:NO]; 弹出相同的 ViewController 时,内存消耗并没有减少而是保持不变。

用户可以多次推送和弹出特定的viewController,这会导致应用程序在RAM中的高内存消耗。

我应该如何优化我的内存消耗?

【问题讨论】:

viewController 的dealloc 弹出后是否会被调用。 @KudoCC 我没查过让我先查一下 您的 viewController 是否在任何其他类中被称为委托,并且委托具有强属性? 您是否将导航控制器存储在任何地方?在 NSArray 或 NSDictionary 或任何其他集合中。似乎你一直在强烈地引用它们。 因为数组会保留那些视图控制器,即使你弹出它们它们也不会被释放。当您从导航控制器弹出视图控制器时,尝试从数组中删除视图控制器。看看这是否会减少您的内存消耗。 【参考方案1】:

您应该使用unwind segue 而不是弹出。

【讨论】:

【参考方案2】:

确保您的视图控制器 (A) 没有引用任何其他视图控制器 (B) 或其拥有的任何对象。 Incase 然后确保 VC-B 没有引用回 VC-A。如果它对 VC-A 有一些引用,则将其设为弱属性。否则,即使 VC 弹出,强保留循环也会将 VC 保留在内存中。

另一件事是检查 VC 中是否有任何闭包,检查其主体是否使用 self 引用任何属性或方法,然后创建 Capture list 以避免保留循环,因为“闭包是引用类型强>”

检查是否有任何你没有释放的 NSNotification 观察者

在 deinit 方法中进行打印调用以检查其是否已释放。

进一步了解内存管理:

https://medium.com/mackmobile/avoiding-retain-cycles-in-swift-7b08d50fe3ef https://www.youtube.com/watch?v=GIy-qnGLpHU

【讨论】:

【参考方案3】:

我想说,我最近几天都在网上搜索我的应用程序内存问题。我在 2 个 UIViewControllers 之间切换。其中一个有一个滚动视图,它保留了所有子视图。事实证明,UIVC 加载了一个新的滚动视图而没有释放前一个。我花了几个小时才意识到这一点。

我所做的是:

在应用程序内部寻找任何类型的死锁,然后搜索具有强属性和其他绝望措施的每个变量。但真正奏效的是:

 @IBAction func backBB(sender: UIBarButtonItem) 
    collectionView.removeFromSuperview()
    self.frontView.removeFromSuperview()
    eventsPhotos.removeAll(keepCapacity: false)
    symbolContainerView.removeFromSuperview()
    self.myScrollView.removeFromSuperview()
    dismissViewControllerAnimated(true, completion: )

我手动删除了一些视图和内容。我已经在“返回”按钮中完成了它,但您可以在 viewWillDisappear(animated: Bool) 等其他方法中执行此操作。

完成此操作后,我在开发人员工具中的分配图表显示内存分配上升和下降...并且它已解决...

【讨论】:

虽然您解决了它是为了您的个人需求,但这似乎不是一个干净的解决方案。我认为有一些更深层次的关键需要弄清楚。【参考方案4】:

如果您的应用设计允许用户一遍又一遍地推送和弹出同一个视图控制器,您可能希望考虑重用同一个视图控制器,并在每次推送时更新其内容。

与其一遍又一遍地创建和销毁它,不如创建一个,设置它的内容并推送它,当它弹出时,保持它随时准备再次显示。下次需要展示的时候,更新一下内容再推送。

【讨论】:

【参考方案5】:

当您关闭视图控制器(或弹出它)时,如果您没有对它进行任何强指针,它将被释放(该控制器由导航控制器或呈现视图控制器保留,因此您通常不'在创建并推送或呈现它时不需要指向它的指针)。

如果没有其他强指针会被释放

【讨论】:

虽然正确,但我认为这不是重点。尽管控制器本身被释放,但有时即使弹出内存使用量也不会减少,就像问题中一样。 查看“废弃内存”以及如何找到它。它与泄漏不同。 developer.apple.com/library/ios/recipes/… @Jonny,因为我也在使用导航控制器,但是我得到了其中处理的页面列表,这会给堆栈带来很多负载,最终会发生崩溃,有没有释放堆栈负载的方法或技术【参考方案6】:

关闭时弹出窗口为零。

[menuPopup_ dismissPopoverAnimated:YES];
menuPopup_ = nil;

【讨论】:

问题不涉及弹出框。 为什么是这个答案?【参考方案7】:

考虑检查您是否在块中引用self。如果这样做,您可能会在弹出 UIViewController 引用后保留它。

要更深入地了解原因,请查看以下答案: How do I avoid capturing self in blocks when implementing an API?

【讨论】:

【参考方案8】:

我认为当您尝试弹出视图控制器时会出现错误,因为导航控制器没有对视图控制器的有效引用,因为它在您推送后被释放。

【讨论】:

【参考方案9】:

尽量避免对 IBOutlets 使用强属性。

【讨论】:

为什么?弱插座在 iOS5 中是相关的,此时视图会被卸载,但现在不会导致问题。 您的意思是,如果我们在 iOS 5 后的 ARC 中将 IBOutlet 声明为强属性或弱属性,则不会有任何区别? 对您的观点感兴趣@jrturton,这是否记录在任何地方?另外,为什么你现在要使用强属性而不是弱属性? @Jeff,Strong 是默认设置,为什么要额外设置?弱属性的要点是当视图被卸载时它们将被取消。视图不再被卸载,所以没有意义。我不知道这是在哪里记录的。 Apple 说“Outlets 通常应该是weak。” Here's the docs.

以上是关于为啥 ARC 在 popViewController 之后不释放内存的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Clippy 建议传递 Arc 作为参考?

为啥在启用 ARC 的项目中不需要维护保留计数

为啥我不能在 ARC 中使用自定义颜色创建 CAGradientLayer?

为啥在 ARC 中发送消息会导致保留周期警告,但属性集不会?

为啥迁移到 ARC 后我的应用程序充满了内存泄漏?

为啥St. Joan of Arc是圣女贞德?Arc是啥意思?