我刚才发现,在我的游戏我的内存使用量只上升时,地砖被感动了,但它永远不会再回去了。由此,我可以告诉有内存泄漏。
然后我就开始使用的Xcode工具,这点我是很新的。所以我也跟着从this article很多东西,尤其是Recording Options
,然后我将模式设置为显示Call Tree
。
我有两个功能,只是将所有的砖沿行/列,然后克隆(使用node.copy()
)结尾的瓷砖所以一切都可以“loopover”,因此该项目的名称。
我觉得好象瓦片克隆可能会造成一些保留周期,但是,它被存储在功能范围内的变量。我跑克隆上的SKAction
后,我从现场使用copiedNode.removeFromParent()
删除瓷砖。
那么,什么可能会导致此内存泄漏?我可能是找错了地方?
我已经缩短这段代码什么,我认为有必要。
声明在类的顶部:
/// Delegate to the game scene to reference properties.
weak var delegate: GameScene!
/// All the cloned tiles currently on the board.
private var cloneTiles = [SKSpriteNode]()
移动瓷砖职能范围内的瓷砖的克隆:
/// A duplicate of the current tile.
let copiedNode = currentTile.node.copy() as! SKSpriteNode // Create copy
cloneTiles.append(copiedNode) // Add as a clone
delegate.addChild(copiedNode) // Add to the scene
let copiedNodeAction = SKAction.moveBy(x: movementDifference, y: 0, duration: animationDuration) // Create the movement action
// Run the action, and then remove itself
copiedNode.run(copiedNodeAction) {
self.cloneTiles.remove(at: self.cloneTiles.firstIndex(of: copiedNode)!)
copiedNode.removeFromParent()
}
功能立即采取行动瓷砖:
/// Move all tiles to the correct location immediately.
private func moveTilesToLocationImmediately() {
// Remove all clone tiles
cloneTiles.forEach { $0.removeFromParent() }
cloneTiles.removeAll()
/* Moves tiles here */
}
有什么我需要声明的weak var
什么?我知道发生周期如何挽留,但不知道为什么它在这段代码存在,因为我删除从cloneTiles
阵列克隆平铺参考。
Mark Szymczyk
帮助)这是发生了什么调用堆栈移动瓷砖功能我双击后(请参阅下面他的回答):
这是确认内存泄漏是由节点克隆不知何故造成的,但我仍然不知道为什么它是从cloneTiles
阵列和现场取出后,该节点仍然被保留。可以在节点是从现场由于某些原因得到清除有问题?
请留下这方面有任何建议或疑问,所以这个问题是可以解决的!
现在我一直在试图让在Xcode工具交手,但我还是很努力寻找此内存泄漏。这里是泄漏面板可以帮助:
即使试图[weak self]
后,我仍然没有运气:
即使泄漏的历史看起来仍然与封闭内[weak self]
相同。
目前,@matt
帮助我解决这个问题。我已经改变了几行代码,通过增加之类的东西[unowned self]
:
// Determine if the tile will roll over
if direction == .up && movementDifference < 0 || direction == .down && movementDifference > 0 {
// Calculate where the clone tile should move to
movementDifference -= rollOverDistance
/// A duplicate of the current tile.
let copiedNode = currentTile.node.copy() as! SKSpriteNode // Create copy
cloneTiles.append(copiedNode) // Add as a clone
delegate.addChild(copiedNode) // Add to the scene
let copiedNodeAction = SKAction.moveBy(x: 0, y: movementDifference, duration: animationDuration) // Create the movement action
// Run the action, and then remove itself
copiedNode.run(copiedNodeAction) { [unowned self, copiedNode] in
self.cloneTiles.remove(at: self.cloneTiles.firstIndex(of: copiedNode)!).removeFromParent()
}
// Move the original roll over tile back to the other side of the screen
currentTile.node.position.y += rollOverDistance
}
/// The normal action to perform, moving the tile by a distance.
let normalNodeAction = SKAction.moveBy(x: 0, y: movementDifference, duration: animationDuration) // Create the action
currentTile.node.run(normalNodeAction) { [unowned self] in // Apply the action
if forRow == 1 { self.animationsCount -= 1 } // Lower animation count for completion
}
不幸的是,我不能让copiedNode
一个weak
财产,因为这将永远是瞬间nil
和unowned
所引起的释放后被看了一则关于参考崩溃。这里也是Cycles & Roots
图,如果这是有帮助的:
感谢您的任何帮助!
我是非常可疑的你管理拷贝节点的方式;你可能会过早地释放它,只有保留周期阻止你发现这个错误。然而,让我们集中精力打破保留周期。
你想要做的就是让一切都进入操作方法weak
,因此没有强烈的捕获由操作方法。然后在操作方法要立即保留这些弱引用,使他们不从你下了消失。这就是所谓的“弱强舞”。像这样:
copiedNode.run(copiedNodeAction) { [weak self, weak copiedNode] in
if let `self` = self, let copiedNode = copiedNode {
// do stuff here
// be sure to log so you know we arrived here at all, as we might not
}
}
我可以帮上仪器前一点点。如果您双击该仪器的moveHorizontally
入口调用树,仪器会显示您的代码被分配泄漏的内存的线。在窗口的底部是一个调用树按钮。如果你点击,你可以反调用树和隐藏系统库。否则,这将使它更容易找到调用树代码。
您可以了解更多关于仪器下面的文章中: