iOS 7 Sprite Kit释放内存

Leh*_*ves 20 memory-management physics game-physics ios sprite-kit

我正在构建一款针对新iOS 7和Sprite Kit的iOS游戏,使用发射器节点和物理来增强游戏性.在开发应用程序时,我遇到了一个严重的问题:您创建了场景,节点和效果,但是当您完成并需要返回主屏幕时,如何释放这些资源分配的所有内存?

理想情况下,ARC应该释放所有内容,应用程序应该恢复到创建场景之前的内存消耗级别,但这不是发生的事情.

我添加了以下代码,作为视图的dealloc方法,它绘制场景并负责在关闭(删除)后删除所有内容:

- (void) dealloc
{
    if (scene != nil)
    {
        [scene setPaused:YES];

        [scene removeAllActions];
        [scene removeAllChildren];

        scene = nil;

        [((SKView *)sceneView) presentScene:nil];

        sceneView = nil;
    }
}
Run Code Online (Sandbox Code Playgroud)
  • sceneView是一个UIView,它是场景的容器
  • scene是SKScene类的扩展,创建所有SKSpriteNode对象

我非常感谢你对此事的任何帮助.

Coc*_*ico 19

我在Sprite Kit中遇到了很多内存问题,我使用技术支持票来获取信息,这可能与此有关.我问的是,开始一个新的SKScene是否会完全释放前一个使用的所有内存.我发现了这个:

由+ textureWithImageNamed分配的底层内存:切换到新的SKScene时可能会或可能不会(通常不会)释放.你不能依赖它.iOS释放由+ textureWithImageNamed缓存的内存:或+ imageNamed:当它看起来合适时,例如当它检测到内存不足的情况时.

如果您希望在完成纹理后立即释放内存,则必须避免使用+ textureWithImageNamed:/ + imageNamed:.创建SKTextures的另一种方法是:首先使用+ imageWithContentsOfFile:创建UIImages,然后通过调用SKTexture/+ textureWithImage :( UIImage*)从生成的UIImage对象创建SKTextures.

我不知道这是否有帮助.


Lea*_*s2D 10

所有这些代码都是多余的.如果代码中没有内存泄漏或保留周期,一旦释放Sprite Kit视图,所有内容都将从内存中清除.

在引擎盖下Sprite Kit采用了缓存机制,但是我们无法控制它,我们也不需要它是否正确实现(可以安全地假设).

如果这不是您在仪器中看到的,请检查保留周期,泄漏.验证是否已调用场景和视图的dealloc.确保没有对视图,场景或其他节点的强引用保留在其他对象(特别是单例和全局变量)中.

  • 嗯,有趣的想法,但不,即使在记忆警告后它也不会下降. (4认同)
  • 可能,它需要明确的测试来验证.也许SK保留缓存的纹理以供以后重用,并且仅在内存警告时释放它们.尝试在模拟器中发送内存警告,然后查看内存是否会丢失. (2认同)

小智 8

经过几天的斗争后,事实上关键是:[sceneView presentScene:nil]; 或者对于Swift:sceneView.presentScene(nil)

这可以在viewDidDisappear中完成.如果没有这个,即使在被解雇之后,你的观点也将继续留在现场,亲爱的生活,并继续咀嚼记忆.


Ale*_*ano 5

斯威夫特3

根据我的个人经验,我在 Xcode 工具的帮助下解决了问题,首先是使用活动监视器立即向我显示了巨大的内存增加,而不是分配和泄漏。

但也有一个有用的方法,调试控制台与

deinit {
       print("\n THE SCENE \(type(of:self)) WAS REMOVED FROM MEMORY (DEINIT) \n")
}
Run Code Online (Sandbox Code Playgroud)

这是查看是否deinit每次要删除场景时都调用的另一个帮助。

你在你的类中从来没有对scene或 的强引用parent,如果你有任何人,你必须将它转换为弱引用,例如:

weak var parentScene:SKScene?
Run Code Online (Sandbox Code Playgroud)

协议也一样,你可以像这个例子一样使用属性将它声明为弱class

protocol ResumeBtnSelectorDelegate: class {
    func didPressResumeBtn(resumeBtn:SKSpriteNode)
}

weak var resumeBtnDelegate:ResumeBtnSelectorDelegate?
Run Code Online (Sandbox Code Playgroud)

ARC 完成了我们需要的所有工作,但是,如果您认为自己忘记正确编写某些属性(初始化、块..),我也在调试阶段使用了一些这样的函数:

func cleanScene() {
    if let s = self.view?.scene {
        NotificationCenter.default.removeObserver(self)
        self.children
            .forEach {
                $0.removeAllActions()
                $0.removeAllChildren()
                $0.removeFromParent()
        }
        s.removeAllActions()
        s.removeAllChildren()
        s.removeFromParent()
    }
}

override func willMove(from view: SKView) {
    cleanScene()
    self.removeAllActions()
    self.removeAllChildren()
}
Run Code Online (Sandbox Code Playgroud)