是啥导致了这种内存泄漏?
Posted
技术标签:
【中文标题】是啥导致了这种内存泄漏?【英文标题】:What's causing this memory leak?是什么导致了这种内存泄漏? 【发布时间】:2015-04-23 22:25:58 【问题描述】:问题
我目前正在使用SpriteKit 构建一个 iPad 游戏。游戏由EZAudio 提供的声音驱动。在运行 Instrumentation 工具来分析我的应用程序后,我注意到 每当显示
GameViewController
时,内存分配就会上升。当我重复显示屏幕(5 次以上)时,它会使应用程序崩溃。我的项目使用ARC。
导航
导航由4个ViewControllers
组成:
-
MenuViewController:显示菜单
CharacterSelectionViewController:它可以让您选择要使用的角色
GameViewController:这让您可以与所选玩家一起玩游戏
ScoreViewController:显示您在游戏中取得的分数
1 - 菜单视图控制器
您可以从这里通过Show (e.g. Push
) 转场导航到CharacterSelectionViewController
。
2 - CharacterSelectionViewController
您可以通过Show (e.g. Push)
segue 导航到GameViewController
。还有一个返回按钮可以返回MenuViewController
,代码如下:
[self.navigationController popViewControllerAnimated:YES];
3 - 游戏视图控制器
-
它首先显示 5 秒倒计时(使用
NSTimer
)
游戏从CharacterSelectionViewController
中选择的角色开始
游戏可以暂停,您可以通过手动Show Detail (e.g. Replace)
segue 退出并返回MenuViewController
。
当游戏结束时,会调用手动Show (e.g. Push)
segue 导航到ScoreViewController
。
它的视图层次结构由三组视图组成——一组用于倒计时,一组用于暂停菜单,一组用于游戏。这些随后被显示/隐藏。请参阅下面的视图层次结构:
4 - ScoreViewController
这允许您退出或重新开始游戏。退出时,按下它会执行Show Detail (e.g. Replace)
segue 到MenuViewController
。如果按下重新启动,它将执行 unwind
到 CharacterSelectionViewController
。
回复
请提供以下方面的答案:
这种泄漏是如何发生的 您对分配和泄漏屏幕截图的任何观察分配
在下面,当我循环浏览应用程序屏幕以重复显示 GameViewController
时,您可以看到分配的增加。我使用Mark Generation
来显示内存分配的增加。
泄漏
在这里您可以看到发生的内存泄漏。这是按大小排序的。
【问题讨论】:
你怎么来和去这个控制器?您要使用 segue 回到以前的控制器吗? 嗨@rdelmar,是的,我通过Show (e.g. Push
) segue 来到这个控制器。然后,我以两种方式之一离开 segue。第一个是通过Show Detail (e.g. Replace)
segue 回到MenuViewController
(层次结构中的两个视图,因此是前一个控制器)。第二个是Show (e.g. Push)
segue 到另一个不是前一个控制器的控制器。 请查看我更新的问题以获得更详细的解释
【参考方案1】:
暂时忽略泄漏;先修复世代积累。
那一代快照是否代表了典型快照之后剩下的内容?通常,您希望显示视图控制器、拍摄快照、隐藏然后显示视图控制器、拍摄快照等...尽可能多地不崩溃(如果不崩溃,则为 10 次)。
然后看看第 3 代或第 4 代,因为这将是每代增长的最稳定表示。
如果它具有代表性,则看起来您正在泄漏视图控制器通常会分配的所有内容。最终,您正在寻找保持一切的对象图的“根”。修复根存在的原因,其余的可能会消失。
我为此写了一篇博客文章。它有点过时了,但分析工作流程保持不变。
http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/
【讨论】:
【参考方案2】:您是如何从各种视图控制器中解脱出来的?我注意到你提到当游戏结束时你正在将另一个 VC 推入堆栈,但我认为这个 VC 链会在某个时候展开回到你的初始菜单? (本质上,我想知道您是否只是在循环播放,因此每次玩游戏时都会向堆栈添加新的 VC。)
要创建一个 unwind segue,只需在 destination VC(即:您的主菜单)中创建一个空方法,如下所示:
- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
// Intentional NOP
(注意:确保它也列在标题中。)
然后,您可以像在情节提要中的任何其他 segue 一样调用它,方法是从有问题的源对象拖动到情节提要中包含源对象的 VC 顶部的退出选项 .这将为您提供可供选择的 segue 列表。 (您可以通过在情节提要中选择源对象来验证转场设置是否正确 - 连接检查器应在 Triggered Segues 部分中列出展开转场。)
【讨论】:
以上是关于是啥导致了这种内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章