导致此内存泄漏的原因是什么?

时间:2015-04-23 22:25:58

标签: ios objective-c memory-management memory-leaks

问题

  

我目前正在使用SpriteKit制作iPad游戏。游戏玩法由EZAudio提供的声音驱动。在运行Instrumentation工具来分析我的应用程序之后,我注意到每当GameViewController显示内存分配都会跳起来。当我反复显示屏幕(5次以上)时,它会崩溃应用程序。我的项目使用ARC

导航

导航包含4个ViewControllers

  1. MenuViewController :显示菜单
  2. CharacterSelectionViewController :它允许您选择要使用的角色
  3. GameViewController :这可让您与选择的玩家一起玩游戏
  4. ScoreViewController :它会显示您在游戏中取得的分数
  5. 1 - MenuViewController

    从此处,您可以通过CharacterSelectionViewController)segue导航至Show (e.g. Push

    2 - CharacterSelectionViewController

    您可以通过GameViewController segue导航至Show (e.g. Push)。还有一个后退按钮,可以使用以下代码返回MenuViewController

    [self.navigationController popViewControllerAnimated:YES];
    

    3 - GameViewController

    1. 首先显示5秒倒计时(使用NSTimer
    2. 游戏以CharacterSelectionViewController
    3. 中选择的角色开头
    4. 游戏可以暂停,允许您退出并通过手动MenuViewController segue返回Show Detail (e.g. Replace)
    5. 当游戏结束时,会调用手动Show (e.g. Push) segue导航到ScoreViewController
    6. 它的视图层次结构由三组视图组成 - 一组用于倒计时,一组用于暂停菜单,一组用于游戏。随后显示/隐藏这些。请参阅下面的视图层次结构:

      GameViewController View Hierarchy

      4 - ScoreViewController

      这允许您退出或重新启动游戏。退出时按下它会执行Show Detail (e.g. Replace) segue到MenuViewController。如果按下重新启动,则会执行unwindCharacterSelectionViewController

      的响应

      请提供以下答案:

      • 如何发生这种泄漏
      • 您从分配和泄漏屏幕截图中获得的任何观察结果

      分配

      下面,您可以看到增加的分配,因为我循环浏览应用程序屏幕以重复显示GameViewController。我使用Mark Generation来显示内存分配的增加。

      Allocations

      泄漏

      在这里您可以看到发生的内存泄漏。这是按尺寸排序的。

      Leaks

2 个答案:

答案 0 :(得分:3)

暂时忽略泄漏;先解决代际吸积问题。

那一代快照是否代表典型快照后剩下的内容?通常,您需要显示视图控制器,拍摄快照,隐藏然后显示视图控制器,拍摄快照等...尽可能多次而不会崩溃(如果不崩溃则为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/

答案 1 :(得分:2)

您是如何从各种视图控制器中展开的?我注意到你提到当游戏结束时你将另一个VC推入堆栈,但我认为这个VC链在某些时候会退回到你的初始菜单? (实质上,我想知道你是否只是循环,因此每次玩游戏时都会在堆栈中添加新的VC。)

要创建一个un-wind segue,只需在目的地 VC中创建一个空方法(即:您的主菜单):

- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
{
    // Intentional NOP
}

(N.B。:确保它也列在标题中。)

然后,您可以像在故事板中的任何其他segue一样调用此方法,方法是将有问题的源对象拖到故事板中包含源对象的VC 顶部的退出选项。这将为您提供可供选择的segue列表。 (您可以通过在故事板中选择源对象来验证是否正确设置了segue - Connections检查器应列出Triggered Segues部分中的展开segue。)