SceneKit presentScene(_withTransition:incomingPointOfView completionHandler)因动态加载的 SCNScene 而崩溃
SceneKit presentScene(_withTransition:incomingPointOfView completionHandler) crash with dynamically loaded SCNScene
我正在尝试从一个场景转换到另一个场景,但是当我调用 presentScene
时出现崩溃!
场景未存储在 class 中或被引用,它们直接加载到 presentScene
调用中。
Xcode 中的崩溃截图:
我的简单最小项目在这里:https://dl.dropboxusercontent.com/u/6979623/SceneKitTransitionTest.zip
MKScene
只是 SCNScene
的一个子 class,因为我想知道场景何时被取消以确保它就是它。
self.gameView!.scene = MKScene(named:"art.scnassets/scene1.scn")
然后我打电话给
let scnView:SCNView = self.gameView! as SCNView
let skTransition:SKTransition = SKTransition.crossFadeWithDuration(1.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
self.sceneToggler = !self.sceneToggler
// transition
scnView.presentScene((self.sceneToggler ? MKScene(named:"art.scnassets/scene1.scn")! : MKScene(named:"art.scnassets/scene2.scn")!), withTransition:skTransition, incomingPointOfView:nil, completionHandler:nil)
如果我在我的 class 中保留对场景的引用,那么它就可以工作——但这不是我想要的。我只是想转换到不同的场景并将当前场景留在 deinited 后面。
为什么会崩溃?
这似乎是一项简单的任务……
这是 SceneKit 中的一个错误。解决方法:在调用 "presentScene" 之前保留对传出场景的引用,并在调用之后释放它。
我能够通过一个更简单的项目重现您的崩溃。它不使用 MKScene
并且不使用通知来触发转换。它在第二次尝试加载时崩溃。
我已经在 https://bugreport.apple.com 上以 rdar://24012973 的形式提交了这个,我想欺骗你,还有你的更长的项目。
这是我的简化 ViewController.swift。在 SCNScene
属性(第 25/29 行)或即时加载(第 24/28 行)之间切换会在正确行为和崩溃行为之间切换。也就是说,
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
失败,并且
nextScene = scene2!
有效。
// ViewController.swift
import Cocoa
import SceneKit
import SpriteKit
class ViewController: NSViewController {
@IBOutlet weak var sceneView: SCNView!
private var sceneToggler:Bool = false
private var scene1: SCNScene? = SCNScene(named:"art.scnassets/scene1.scn")
private var scene2: SCNScene? = SCNScene(named:"art.scnassets/scene2.scn")
private func nextSceneToLoad() -> SCNScene {
let nextScene: SCNScene
if (sceneToggler) {
//nextScene = SCNScene(named:"art.scnassets/scene1.scn")!
nextScene = scene1!
print ("scene1")
}
else {
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
//nextScene = scene2!
print ("scene2")
}
print (nextScene)
sceneToggler = !sceneToggler
return nextScene
}
override func mouseUp(theEvent: NSEvent) {
let skTransition:SKTransition = SKTransition.fadeWithDuration(5.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
sceneView.presentScene(nextSceneToLoad(),
withTransition:skTransition,
incomingPointOfView:nil, completionHandler:nil)
super.mouseUp(theEvent)
}
}
我正在尝试从一个场景转换到另一个场景,但是当我调用 presentScene
时出现崩溃!
场景未存储在 class 中或被引用,它们直接加载到 presentScene
调用中。
Xcode 中的崩溃截图:
我的简单最小项目在这里:https://dl.dropboxusercontent.com/u/6979623/SceneKitTransitionTest.zip
MKScene
只是 SCNScene
的一个子 class,因为我想知道场景何时被取消以确保它就是它。
self.gameView!.scene = MKScene(named:"art.scnassets/scene1.scn")
然后我打电话给
let scnView:SCNView = self.gameView! as SCNView
let skTransition:SKTransition = SKTransition.crossFadeWithDuration(1.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
self.sceneToggler = !self.sceneToggler
// transition
scnView.presentScene((self.sceneToggler ? MKScene(named:"art.scnassets/scene1.scn")! : MKScene(named:"art.scnassets/scene2.scn")!), withTransition:skTransition, incomingPointOfView:nil, completionHandler:nil)
如果我在我的 class 中保留对场景的引用,那么它就可以工作——但这不是我想要的。我只是想转换到不同的场景并将当前场景留在 deinited 后面。
为什么会崩溃? 这似乎是一项简单的任务……
这是 SceneKit 中的一个错误。解决方法:在调用 "presentScene" 之前保留对传出场景的引用,并在调用之后释放它。
我能够通过一个更简单的项目重现您的崩溃。它不使用 MKScene
并且不使用通知来触发转换。它在第二次尝试加载时崩溃。
我已经在 https://bugreport.apple.com 上以 rdar://24012973 的形式提交了这个,我想欺骗你,还有你的更长的项目。
这是我的简化 ViewController.swift。在 SCNScene
属性(第 25/29 行)或即时加载(第 24/28 行)之间切换会在正确行为和崩溃行为之间切换。也就是说,
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
失败,并且
nextScene = scene2!
有效。
// ViewController.swift
import Cocoa
import SceneKit
import SpriteKit
class ViewController: NSViewController {
@IBOutlet weak var sceneView: SCNView!
private var sceneToggler:Bool = false
private var scene1: SCNScene? = SCNScene(named:"art.scnassets/scene1.scn")
private var scene2: SCNScene? = SCNScene(named:"art.scnassets/scene2.scn")
private func nextSceneToLoad() -> SCNScene {
let nextScene: SCNScene
if (sceneToggler) {
//nextScene = SCNScene(named:"art.scnassets/scene1.scn")!
nextScene = scene1!
print ("scene1")
}
else {
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
//nextScene = scene2!
print ("scene2")
}
print (nextScene)
sceneToggler = !sceneToggler
return nextScene
}
override func mouseUp(theEvent: NSEvent) {
let skTransition:SKTransition = SKTransition.fadeWithDuration(5.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
sceneView.presentScene(nextSceneToLoad(),
withTransition:skTransition,
incomingPointOfView:nil, completionHandler:nil)
super.mouseUp(theEvent)
}
}