简体   繁体   English

在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃

[英]Removing SCNNode nodes from scene.rootNode is causing a crash, in SceneKit

I am trying to remove set of nodes from my scene which represent a path.我试图从我的场景中删除一组代表路径的节点。 They are a combination of SCNSphere geometry nodes, and custom geometry representing lines, created using SCNGeometrySource and SCNGeometryElement.它们是 SCNSphere 几何节点和表示线的自定义几何的组合,使用 SCNGeometrySource 和 SCNGeometryElement 创建。

I am not retaining these nodes in any kind of array.我不会将这些节点保留在任何类型的数组中。 Instead, I search the first level of the node tree of the rootNode in the scene for these nodes, by their name, and the subsequent call an action sequence that makes them fade out, and they should remove themselves from the root node.相反,我在场景中 rootNode 的节点树的第一级搜索这些节点,通过它们的名称,然后调用一个使它们淡出的动作序列,并且它们应该从根节点中移除自己。

The code is as follows:代码如下:

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()
}

where:在哪里:

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
}

The lineNodes() function is basically the same. lineNodes() 函数基本相同。

I switched on Zombie Objects to trace where the error is coming from, and I always get the same error: a reference to SceneKit`C3DNodeRemoveFromParentNode as the last thing to call on the thread, and a EXC_BAD_ACCESS (code=1, address... ).我打开 Zombie Objects 来跟踪错误来自哪里,但我总是得到相同的错误:对 SceneKit`C3DNodeRemoveFromParentNode 的引用作为线程上调用的最后一件事,以及 EXC_BAD_ACCESS(代码 = 1,地址... )。

The clearPath() function is the only place in the entire app that I am calling 'RemoveFromParentNode'. clearPath() 函数是整个应用程序中唯一被我称为“RemoveFromParentNode”的地方。

The nodes don't have physics bodies on them and are not being retained anywhere elsewhere.节点上没有物理实体,也不会保留在其他任何地方。

Any thoughts as to how to resolve this?关于如何解决这个问题的任何想法?

EDIT 28/4/18:编辑 28/4/18:

Here is a crash report of the thread where it occurs.这是发生它的线程的崩溃报告。 It would appear that removeObjectFromChildNodesAtIndex is being called twice...看起来 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

EDIT 30/04/18编辑 30/04/18

I continued to add other features to the app, where I needed to remove nodes using SCNAction.removeFromParentNode().我继续向应用程序添加其他功能,在那里我需要使用 SCNAction.removeFromParentNode() 删除节点。 I isolated those as well to cause the problem independently of the above code.我也隔离了这些以独立于上述代码导致问题。

These are called more frequently on the SCNRendererDelegate update as each new nodes are generated.随着每个新节点的生成,这些在 SCNRendererDelegate 更新时被更频繁地调用。

I also tried to use removeFromParentNode() directly on the node using SCNAction.run block, and the same issue occurs.我还尝试使用 SCNAction.run 块直接在节点上使用 removeFromParentNode() ,并且发生了同样的问题。

When you use SCNAction.removeFromParentNode() you aren't removing the node, you have to remove the node it's self.当您使用 SCNAction.removeFromParentNode() 时,您不会删除节点,您必须删除它自己的节点。 If you remove the path or action you are essentially make a value nil so when the path or action is called there is now a nil value and it crashes.如果您删除路径或操作,您本质上是将值设为 nil,因此当调用路径或操作时,现在有一个 nil 值并且它会崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM