gpt4 book ai didi

傻瓜式 Swift SpriteKit ARC

转载 作者:可可西里 更新时间:2023-11-01 00:51:42 26 4
gpt4 key购买 nike

我一直在努力思考强大的引用循环,但我很挣扎。我一直在阅读 Apple 和某些网站上的文档,但我觉得它们并没有真正解决我的问题。

我知道你必须使用 weak 和 unowned 取决于对象是否可以为 nil。所以说你必须像这样上 2 节课

class Person {
var dog: Dog?
....
}

class Dog {
weak var person: Person?
}

相互引用我知道其中一个必须使用 weak/unowned。这是大多数教程中看到的经典示例。

我也见过这样的例子,它们对我来说也很有意义

class Person {

unowned let gameScene: GameScene

init(scene: GameScene) {
self.gameScene = scene
....
}

我也明白 NSTimers 如果不失效的话会导致强引用循环。我没有使用 NSTimers,所以这应该不是问题。

我还了解到协议(protocol)也会导致内存泄漏,因此他们处理它们的方法是使其成为一个类协议(protocol)

protocol TestDelegate: class { }

我试图引用协议(protocol)的地方使它成为一个弱属性

 class: SomeClass {

weak var myDelegate: TestDelegate?

}

最后我知道了我像这样捕获 self 的闭包

SKAction.runBlock { [unowned self] in
self.player.runAction....
}

然而,当谈到我的实际 spritekit 游戏时,我似乎到处都有引用循环,即使是简单的类,我也肯定不会引用另一个类,我不明白为什么。

所以我的主要问题是

1) 是所有属性都创建强引用循环还是仅在类初始化之前创建全局属性?

2) 还有哪些其他事情可能会在我的简单类中创建强引用循环?

例如我正在使用一个创建平台的类

class Platform: SKSpriteNode {

/// basic code to create platforms
/// some simple methods to rotate platforms, move them left or right with SKActions.

现在我有类似这样的类用于陷阱、敌人等。它们通常只是设置 Sprite 属性(物理体等)并有一些方法来设置它们的动画或旋转它们。它们没有什么特别的,特别是在引用其他类或场景方面。

在我的 gameScene 中,我有一个创建平台的方法(对于敌人、陷阱等也是一样)

func createPlatform() {

let platform1 = Platform(.....
platformNode.addChild(platform1)

let platform2 = Platform(....
platformNode.addChild(platform2)

let platform3 = Platform(...
platformNode.addChild(platform3)

// platform node is just a SKNode in the gameScene to help maintain the difference zPositions of my objects.

}

当我运行分配时,我可以看到 3 个平台中只有 1 个进入 transient ,2 个在我切换到我的 menuScene 时保持持久状态。奇怪的是,总是只有 1 个被删除,不管我是否更改顺序或创建/删除某些平台。所以看起来他们正在创建强引用,除了 1。所以如果我重玩我的关卡几次,我可以很快在内存中拥有 50-100 个持久平台。因此,我的场景也没有 deinit,这会浪费更多内存。

另一个例子是

class Flag {
let post: SKSpriteNode
let flag: SKSpriteNode

init(postImage: String, flagImage: String) {

post = SKSpriteNode(imageNamed: postImage)
...


flag = SKSpriteNode(imageNamed: flagImage)
...
post.addChild(flag)
}
}

同样的问题。我在我的场景中创建了一些标志,有时标志不会被删除,有时会。同样,此类不引用任何场景或自定义类,它只是创建一个 Sprite 并为其设置动画。

在我的场景中,我有一个标志的全局属性

 class GameScene: SKScene {

var flag: Flag!

func didMoveToView...

}

如果标志本身不引用 GameScene,为什么会创建强引用?我也不能用

weak var flag: Flag!

因为一旦标志被初始化,我就会崩溃。

这样做时我是否明显遗漏了什么?在 Instruments 中找到它们有什么好技巧吗,因为这对我来说似乎很疯狂。这让我很困惑,主要是因为我的类非常简单,没有引用其他自定义类、场景、 View Controller 等。

最佳答案

感谢您的所有回答,尤其是 appzYourLift 和您的详细回复。

我整天都在研究我的 spriteKit 项目,也在 playground 上做了很多试验,我的游戏现在完全没有泄漏,没有找到强大的引用循环。

实际上,我在仪器中看到的很多泄漏/持久类只是因为其他东西没有解除分配而存在。

似乎永远重复的 Action 导致了我的泄密。我所要做的就是遍历场景中的所有节点并删除它们的 Action 。

这个问题对我有帮助

iOS 7 Sprite Kit freeing up memory

更新:我最近再次访问了这个主题,因为我觉得不必手动删除节点上的操作是不必要的,而且可能会变得很麻烦。经过更多研究,我发现了(我的)内存泄漏的确切问题。

像这样的“SKAction 永远重复”显然会导致泄漏。

let action1 = SKAction.wait(forDuration: 2)
let action2 = SKAction.run(someMethod)
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))

所以需要改成这样才不会造成泄漏

 let action1 = SKAction.wait(forDuration: 2)
let action2 = SKAction.run { [weak self] in
self?.someMethod()
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))

这直接来 self 所做的 Apple 错误报告。

关于傻瓜式 Swift SpriteKit ARC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35798496/

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