在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃
Posted
技术标签:
【中文标题】在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃【英文标题】:Removing SCNNode nodes from scene.rootNode is causing a crash, in SceneKit 【发布时间】:2018-10-07 16:47:37 【问题描述】:我正在尝试从我的场景中删除一组代表路径的节点。它们是使用 SCNGeometrySource 和 SCNGeometryElement 创建的 SCNSphere 几何节点和自定义几何表示线的组合。
我不会在任何类型的数组中保留这些节点。相反,我在场景中 rootNode 的节点树的第一级搜索这些节点,按它们的名称,然后调用一个使它们淡出的动作序列,并且它们应该从根节点中删除自己。
代码如下:
func clearPath()
//
let disappear = SCNAction.fadeOut(duration: 0.1)
let remove = SCNAction.removeFromParentNode()
let sequence = SCNAction.sequence([disappear, remove])
if let pathNodesToRemove = pathNodes()
//
for node in pathNodesToRemove
//
node.removeAllActions()
node.runAction(sequence)
if let lineNodesToRemove = lineNodes()
for node in lineNodesToRemove
//
node.removeAllActions()
node.runAction(sequence)
path.removeAll()
地点:
func pathNodes() -> [SCNNode]?
//
...
let nodes = rootNode.childNodes.filter (node) -> Bool in
//
guard let name = node.name else return false
if name.hasPrefix(configurationComponent.id) &&
name.range(of:"_PATH") != nil
return true
else
return false
return nodes
lineNodes()函数基本相同。
我打开 Zombie Objects 以跟踪错误的来源,但我总是得到相同的错误:对 SceneKit`C3DNodeRemoveFromParentNode 的引用作为线程上调用的最后一件事,以及 EXC_BAD_ACCESS(代码=1,地址... )。
clearPath() 函数是整个应用程序中我调用“RemoveFromParentNode”的唯一位置。
节点上没有物理实体,也没有保留在其他任何地方。
关于如何解决这个问题的任何想法?
28/4/18 编辑:
这里是它发生的线程的崩溃报告。似乎 removeObjectFromChildNodesAtIndex 被调用了两次......
Thread 9 name: Dispatch queue: com.apple.scenekit.renderingQueue.Air_Relay.ARTCSCNView0x104126720
Thread 9 Crashed:
0 SceneKit 0x00000001957d668c C3DNodeRemoveFromParentNode + 40
1 SceneKit 0x0000000195826e28 -[SCNNode __removeObjectFromChildNodesAtIndex:] + 184
2 SceneKit 0x0000000195826e28 -[SCNNode __removeObjectFromChildNodesAtIndex:] + 184
3 SceneKit 0x0000000195827350 -[SCNNode removeFromParentNode] + 396
4 SceneKit 0x000000019593e9fc -[SCNActionRemove updateWithTarget:forTime:] + 92
5 SceneKit 0x0000000195907cb8 SCNCActionSequence::cpp_updateWithTargetForTime+ 2202808 (SCNNode*, double) + 316
6 SceneKit 0x00000001957bcfb0 SCNActionApply + 112
7 SceneKit 0x0000000195853d2c _applyActions + 236
8 CoreFoundation 0x00000001814dccbc __CFDictionaryApplyFunction_block_invoke + 24
9 CoreFoundation 0x00000001814c3f98 CFBasicHashApply + 132
10 CoreFoundation 0x00000001814cdb64 CFDictionaryApplyFunction + 288
11 SceneKit 0x0000000195853b5c C3DAnimationManagerApplyActions + 92
12 SceneKit 0x000000019583b054 -[SCNRenderer _update:] + 656
13 SceneKit 0x000000019583d018 -[SCNRenderer _drawSceneWithNewRenderer:] + 252
14 SceneKit 0x000000019583d69c -[SCNRenderer _drawScene:] + 84
15 SceneKit 0x000000019583daa0 -[SCNRenderer _drawAtTime:] + 728
16 SceneKit 0x00000001958e446c -[SCNView _drawAtTime:] + 512
编辑 30/04/18
我继续向应用程序添加其他功能,我需要使用 SCNAction.removeFromParentNode() 删除节点。我也隔离了这些,以独立于上述代码引起问题。
随着每个新节点的生成,这些在 SCNRendererDelegate 更新中被更频繁地调用。
我还尝试使用 SCNAction.run 块直接在节点上使用 removeFromParentNode() ,并且发生了同样的问题。
【问题讨论】:
如果我有一个保留周期,即使它们没有存储在数组中,我也会在 removeNodes 上崩溃。尝试在 Leaks 中检查您的参考计数。 pathNodes() 和 lineNodes() 是否有可能返回一个公共节点? path.removeAll() 有什么作用? (clearPath 方法的最后一行) 【参考方案1】:当您使用 SCNAction.removeFromParentNode() 时,您并没有删除节点,您必须删除它自己的节点。如果您删除路径或操作,您实际上是在创建一个 nil 值,因此当调用路径或操作时,现在有一个 nil 值并且它崩溃了。
【讨论】:
以上是关于在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SceneKit 从 COLLADA (.dae) 文件中获取几何图形
从 SceneKit 中的 SCNGeometry 中提取人脸信息