gpt4 book ai didi

swift - Assets 单例和引用循环

转载 作者:可可西里 更新时间:2023-11-01 01:50:40 25 4
gpt4 key购买 nike

我目前有一个 Assets 单例类,可以让我访问纹理、声音和音乐。当我和我的伙伴正在经历我们项目的内存管理阶段时,我们意识到我们可能会产生严重的泄漏,并且根据我对 Xcode 工具的使用,我们最大的问题可能集中在这个单例类上。虽然肯定存在其他泄漏,但我们注意到在 map 屏幕和游戏屏幕之间来回移动时,有大约 100 mb 的相当稳定的增加,这似乎对应于我们的 11 个 map Assets 。在这种情况下,我的问题是:

下面的代码是否会创建一个保留循环,如果是,是否可以通过单例类的存在来管理它,或者我们是否应该将其分解为 s.t.纹理图集是分开保存的?

func transitionToMapScreen()
{
//I hope this isn't necessary eventually, but we were trying to ensure all game textures and emitters were deallocated
Assets.sharedInstance.deallocateGameAssets()

gameScene = GameScene()

Assets.sharedInstance.preloadMap
{
[unowned self] in

let mapScene = MapScreen(fileNamed: "MapScreen")!
mapScene.preCreate()
mapScene.scaleMode = self.scaleMode

// Transition with a fade animation
let reveal = SKTransition.fade(withDuration: 2.0)

let fadeMusic = SKAction.run
{
Assets.sharedInstance.bgmTitlePlayer?.setVolume(1.0, fadeDuration: 1.0)

Assets.sharedInstance.bgmTitlePlayer?.play()

Assets.sharedInstance.bgmGamePlayer?.setVolume(0.0, fadeDuration: 1.0)
}

let stopGameMusic = SKAction.run
{
Assets.sharedInstance.bgmGamePlayer?.stop()
}

let transitionAction = SKAction.run
{
self.view?.presentScene(mapScene, transition: reveal)
}

self.run(SKAction.sequence([SKAction.wait(forDuration: 1.0), fadeMusic, SKAction.group([stopGameMusic, transitionAction])]))

} // end Assets.sharedInstance.preloadMap completion block*/
}

根据我对 Swift 中保留循环的理解,这不是创建对 Assets 类的自引用并造成内存泄漏吗?这是否可以解释我们的 map Assets 保留在内存中的行为?如果是这样,管理它的正确方法是什么?

最佳答案

我想在这里发布这篇文章,供那些可能正在寻找与寻找保留周期相关的类似问题的答案以解释内存增长问题的人使用。首先,非常感谢所有帮助我停止我的神经元随机疯狂尝试寻找保留周期的人,这些保留周期没有(或者没有足够大到重要)。现在:

首先,保留周期确实很可怕,但是使用工具找到它们,然后按照 Apple 的建议进行管理,因为 Swift 4.2 是合适的:

something()
{
[weak self] in

guard let self = self else { return }

self.whatever()
}

我见过一些人争辩说,您应该确定 unowned 还是 weak 是否有意义——老实说,这消除了猜测并且容易得多。我确实发现无主崩溃至少对我们来说是罕见的,但我不会对您的应用发表意见,这可以解决问题。现在,那么,一旦你打扫完房子:

我们发现我们的内存增长问题并非源于我们固有的 Assets 单例类,而是源于我们的纹理图集的庞大规模以及这些图集的相应重叠使用。我怎么推荐这个讨论都不为过:How does SKTexture caching and reuse work in SpriteKit? .这将从概念上解释您可能会比我更好地面对 map 集的问题。

不过,总而言之:SpriteKit 管理纹理图集的分配,因此您必须了解,如果您有一个经常加载的非常大的图集,它可能不会像您期望的那样管理它(我仍然没有足够的细节以更好的方式描述它,但正如我所说,请引用上面的讨论以及苹果关于 SKTextureAtlas 的开发人员指南:https://developer.apple.com/documentation/spritekit/sktextureatlas)。

现在,与 Apple 的讨论相关,我注意到这一行,我认为它真的应该加粗并显示为红色:“SpriteKit 在访问其中一个图集的纹理时隐式加载图集。”这对于解决我认为是我们潜在问题的问题至关重要:出于某种原因,我们有几个地方通过单个实例访问图集中的纹理——您必须认识到,在大型图集的情况下,SpriteKit 将随后加载您的整个海量图集存入内存。所以我不再轻视 Apple 的笔记来管理你的图集大小。 map 集适用于始终一起使用并且将被绘制在一起的 Assets 。将不同的 Assets 加载到 map 集中是我们的错误。我们正在相应地重组我们管理这些内容的方式。

关于swift - Assets 单例和引用循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54445957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com