- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在努力思考强大的引用循环,但我很挣扎。我一直在阅读 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/
我想完全理解 Java 上的二维 RTree,但我在解释中迷路了,我希望有人能告诉我它们是如何工作的。 我对他们的了解是这样的: 您从具有最大条目数 M 的节点列表开始,当您尝试获得更多值时,您必须拆
我想与 4 个国家足球队(英格兰、比利时、德国和法国)和 n 个日期一起工作 Date Matches 16.03 England X Brazil 16.03
NSInvocation 究竟是如何工作的?有好的介绍吗? 我在理解以下代码(来自 Cocoa Programming for Mac OS X,第 3 版)的工作原理方面特别有问题,但我也能够独立于
我正在尝试学习如何在亚马逊云上成功部署 Symfony2 应用程序。有用的是我从空白的 Ubuntu 开始,安装了 lamp-server^、svn ……其他一些好东西,它运行得很好。 问题:所有 A
我一直在努力了解 getter 和 setter,但没有深入了解。我读过 JavaScript Getters and Setters和 Defining Getters and Setters只是没
如果我没看错,那么 Controller 的功能就是处理 POST 数据,并在技术上通过模型对应用程序(例如数据库)的状态进行更改。 据我了解,View 也从 Model 获取数据。 这就是我对工作流
我正在尝试将日期从一种格式转换为另一种格式:来自例如“2005 年 10 月 29 日”至 2005-10-29。我有一个包含 625 个日期的列表。我使用 Awk。 大多数情况下,转换都有效。然而,
我是一名优秀的程序员,十分优秀!