我创建了一个与Terraria Mod协同工作的应用程序。该mod通过TCP将清单更新作为JSON对象发送到应用程序,然后在触摸栏中显示清单。
我遇到的问题是,一旦收到更新,就会有连续的内存泄漏,随着时间的流逝,这些泄漏总计达数百MB。这会减慢应用程序的运行速度。
复制self
时,我发现的内存泄漏之一发生在下面的第二行代码中:
func scaleEffect(_ scaleMultiplier: CGFloat, maxLength: CGFloat = .infinity) throws -> NSImage {
guard let image = self.copy() as? NSImage else {
throw RuntimeError.error("Error copying image")
}
image.size.width *= scaleMultiplier
image.size.height *= scaleMultiplier
if image.size.width > maxLength || image.size.height > maxLength {
let ratio = image.size.width / image.size.height
let const: CGFloat = maxLength
if image.size.width >= image.size.height {
image.size.width = const
image.size.height = const / ratio
} else {
image.size.height = const
image.size.width = const * ratio
}
}
return image
}
我什至不知道为什么会泄漏内存,但这只是发生的许多泄漏之一!
另一个使我感到困惑的内存泄漏是,一个_ContiguousArrayStorage<DisplayList.Item>
实例的实例泄漏。我不知道这个类是什么,也不知道它的专业化类型是什么。我所知道的是,我有一个名为Item
的课程,仅此而已。这种特定的泄漏似乎确实引用了大多数其他泄漏的对象,但是它自己的内存图看起来像这样:
我知道...令人困惑,对吧?
您可以找到应用程序的GitHub存储库here。我创建了一种无需模版就可以发送清单更新的方法,如here所述。
谢谢。
编辑:
我已经追踪到大多数内存泄漏是由于使用了上面声明的nsImage.scaleEffect(_ scaleMultiplier:, maxLength:)
方法。在下面的评论中,Rob提到他注意到,如果您删除了ObservableTimer
中用于脉动的StatsView
实例,泄漏就会减少。
经过进一步的试验,我意识到这意味着仅在状态更改和SwiftUI视图重新加载后才创建泄漏,因为再次调用了上述方法。
如果您删除this line中的, let scaledImage = try? image.scaleEffect(spriteScaleMultiplier, maxLength: maxSpriteLength)
并将this line中的scaledImage
更改为image
,则泄漏会再次减少。
在评论StatsView
的任何初始化时,我只调查了InventoryView
,但是InventoryView
实例包含ItemView
实例,也称为上述方法。
TL; DR:我提到的第一种方法比Phil Swift在 EXTREME BUCKET DEMO 中破坏的那个桶更易泄漏,但是我仍然需要帮助找到FLEXSEAL®来解决泄漏! (老模因,但是这已经是十年的末日了……)。