gpt4 book ai didi

ios - Spritekit removeFromParent() 关于 iOS9 的问题

转载 作者:行者123 更新时间:2023-11-30 14:02:27 25 4
gpt4 key购买 nike

我的应用程序根据传入事件动态创建多个 SKNode 和 SKSpriteNode。当我尝试清理过时的节点及其包含的子节点时,我使用node.removeFromParent()。

但是,一旦我尝试在所有节点层上使用 deinit 的清理代码,我就会立即获得 EXC_BAD_ACCESS。

我认为最安全的版本应该是下面的代码,它也因上述异常而严重失败:

deinit {
if self.child1.parent!.children.contains(self.child1) {
self.child1.removeFromParent()
}
}

总结一下:子节点仍然有一个父节点(self.child.parent != nil)。即使在其父级的子级列表中找到 child1 也会说:嘿,我还在那里,po child1 和 po child1.parent!显示有效的节点对象。但removeFromParent()仍然会使应用程序崩溃。

deinit() 中的日志消息显示每个对象仅调用一次反初始化器...

我能够在一个小项目中重现它。基本的东西应该包含在这两个类中:

import SpriteKit

public class ContainerNode : SKNode {

private let myNode : CustomNode

override init() {
self.myNode = CustomNode()
super.init()
self.addChild(self.myNode)
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

deinit {
self.myNode.removeFromParent()
self.removeFromParent()
}

}

public class CustomNode : SKNode {

private let containerNode : SKNode
private let child1 : SKNode

override public init() {

self.child1 = SKNode()

self.containerNode = SKNode()

super.init()

self.containerNode.addChild(self.child1)

self.addChild(self.containerNode)
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

deinit {

if self.child1.parent!.children.contains(self.child1) {
self.child1.removeFromParent() // EXC_BAD_ACCESS here !!
}

self.containerNode.removeFromParent()
self.removeFromParent()
}

}

class GameScene: SKScene {

private var myNodes = [ContainerNode]()

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

if myNodes.count >= 5 {

self.removeAllChildren()

self.myNodes.removeAll()

}

for touch in touches {

let location = touch.locationInNode(self)

let node = ContainerNode()
node.position = location

myNodes.append(node)

self.addChild(node)

}
}
}

class GameViewController: UIViewController {

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

if let scene = GameScene(fileNamed:"GameScene") {

UIApplication.sharedApplication().idleTimerDisabled = true

let skView = self.view as! SKView

skView.multipleTouchEnabled = true;
scene.scaleMode = .ResizeFill

skView.presentScene(scene)
}
}

override func shouldAutorotate() -> Bool {
return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

override func prefersStatusBarHidden() -> Bool {
return true
}
}

代码可以粘贴到标准宇宙飞船演示中(它加载演示的游戏场景文件)。单击背景 6 次。前 5 次单击将节点添加到场景中。第六次单击时,所有节点都将以编程方式删除,这将使应用程序崩溃。

任何想法表示赞赏。这是 Apple 的错误还是我错过了什么?

XCode 7 GM,在模拟器和 iPhone5 上崩溃...

最佳答案

首先这句话

The most safe version I think should be the following piece of code and it badly fails with the mentioned exception as well:

应该从不指示存在此符号的代码块!:)

现在,您的代码中存在一些错误,但基本上您过度删除了节点。

1。 ContainerNode 中的 deinit 错误

当您删除节点的父节点(并且没有对该节点的其他强引用)时,它会自动删除(感谢 ARC)并释放其内存。而且,非常重要的是,这种情况会递归地发生在 children 身上。

因此您的 ContainerNode 类变为:

public class ContainerNode : SKNode {

private let myNode : CustomNode

override init() {
self.myNode = CustomNode()
super.init()
self.addChild(self.myNode)
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// deinit {
// self.myNode.removeFromParent()
// self.removeFromParent()
// }
}

2。 CustomNode 也有同样的问题

请按照如下所述更新您的代码。

public class CustomNode : SKNode {

private let containerNode : SKNode
private let child1 : SKNode

override public init() {

self.child1 = SKNode()

self.containerNode = SKNode()

super.init()

self.containerNode.addChild(self.child1)

self.addChild(self.containerNode)
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// deinit {
//
// if self.child1.parent!.children.contains(self.child1) {
// self.child1.removeFromParent() // EXC_BAD_ACCESS here !!
// }
//
// self.containerNode.removeFromParent()
// self.removeFromParent()
// }

}

3。游戏 View Controller

出于某种原因,您从 GameViewController 中删除了这一行

skView.showsNodeCount = true

如果您将其添加到代码中,请在这里说

class GameViewController: UIViewController {

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

if let scene = GameScene(fileNamed:"GameScene") {

UIApplication.sharedApplication().idleTimerDisabled = true

let skView = self.view as! SKView

skView.multipleTouchEnabled = true;
scene.scaleMode = .ResizeFill

skView.presentScene(scene)

skView.showsNodeCount = true // <<< add this
}
}

您将能够在屏幕右下角看到添加到图表中的节点数。您将看到每次点击后都会添加 4 个新节点。在第 6 个节点之后,所有节点(除了场景)都被删除,然后立即再次添加 4 个节点。

enter image description here

希望这有帮助。

关于ios - Spritekit removeFromParent() 关于 iOS9 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32826209/

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