我有一个奇怪的问题,或者我正在做的事情很奇怪 .

我有一个ARKit应用程序,它会在检测到条形码时显示一个嵌入了数据视图的SCNNode . 当点击数据视图时,我想从节点中分离它并将其作为子视图添加到主视图中 . 再次点击时,我想重新连接到SCNNode .

我发现this code至少可以完成我想要的部分内容 .

我的应用程序第一次运行良好 . 数据显示在SCNNode中:

{
    let transform = anchor.transform
    let label = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)


    let plane = SCNPlane(width: self.sceneView.bounds.width/2000, height: self.sceneView.bounds.height/2000/2)  //was sceneView

    label.update(dataItem.title!, andValue: dataItem.value!, withTrend: dataItem.trend)
    label.delegate = self

    plane.firstMaterial?.blendMode = .alpha
    plane.firstMaterial?.diffuse.contents = label.view //self.contentController?.view

    let planeNode = SCNNode(geometry: plane)
    planeNode.opacity = 0.75
    planeNode.simdPosition = float3(transform.columns.3.x + ( base * count), 0, transform.columns.3.z)
    node.addChildNode(planeNode)
    childControllers[label] = planeNode
    label.myNode = planeNode
    label.parentNode = node

    if("Speed" == anchorLabels[anchor.identifier]!) {

        let constraint = SCNBillboardConstraint()
        planeNode.constraints = [constraint]
    }  
    count += 1
}

SimpleValueViewController 有一个点击识别器,可以在子视图和节点内切换 .

这是问题所在 .

它很好 . 视图位于节点内 .

点击时,它会附加到主视图 .

当再次点击时,节点只显示一个白色方块,并且点击不再起作用 .

我终于放弃并重新创建了一个新的viewController,但它仍然偶尔失败,只有一个白色方块:

这是分离/附加的代码它是非常混乱的,因为我已经敲了一会儿:

func detach(_ vc:Detachable) {

    if let controller = vc as? SimpleValueViewController {
        controller.view.removeFromSuperview();
        self.childControllers.removeValue(forKey: controller)
        let node = controller.myNode
        let parent = controller.parentNode
        let newController = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)
        if let v = newController.view {
            print("View: \(v)")
            newController.myNode = node
            newController.parentNode = parent
            newController.update(controller.titleString!, andValue: controller.valueString!, withTrend: controller.trendString!)
            newController.delegate = self
            newController.scaley = vc.scaley
            newController.scalex = vc.scalex
            newController.refreshView()

            let plane = node?.geometry as!  SCNPlane
            plane.firstMaterial?.blendMode = .alpha
            plane.firstMaterial?.diffuse.contents = v
           // newController.viewWillAppear(false)
            newController.parentNode?.addChildNode(newController.myNode!)
            newController.attached = false;
            self.childControllers[newController] = node
        }  
    } else {
        print("Not a know type of controller")
    }
}

func attach(_ vc:Detachable) {
    DispatchQueue.main.async {
    if let controller = vc as? SimpleValueViewController {
        self.childControllers.removeValue(forKey: controller)
        let newController = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)
        let node = controller.myNode
        let parent = controller.parentNode

        let scaleX = vc.scalex!/self.view.frame.size.width
        let scaleY = vc.scaley!/self.view.frame.size.height
        let scale = min(scaleX, scaleY)

        let transform = CGAffineTransform(scaleX: scale, y: scale)
        newController.view.transform = transform
        newController.myNode = node
        newController.parentNode = parent
        newController.update(controller.titleString!, andValue: controller.valueString!, withTrend: controller.trendString!)
        newController.delegate = self
        newController.scaley = vc.scaley
        newController.scalex = vc.scalex
        node?.removeFromParentNode()
        self.childControllers[newController] = node

        newController.attached = true

        self.view.addSubview(newController.view)
    } else {
        print("Not a know type of controller to attach")
    }
    }
}

我认为这是一个计时问题,因为从笔尖加载一个视图是懒惰的,所以我在SimpleValueViewController(nibName:“SimpleValueViewController”,bundle:nil)之后进入睡眠1秒,但这没有帮助 .

还有什么我可以尝试的吗?我离基地很远?我希望每次切换数据时都不必重新创建视图控制器 .

提前致谢 .

渲染功能:

func renderer(_ renderer:SCNSceneRenderer,didAdd node:SCNNode,for anchor:ARAnchor){

// func renderer(_ renderer:SCNSceneRenderer,nodeFor anchor:ARAnchor) - > SCNNode? {

// updateQueue.async {

//Loop through the near and far data and add stuff

let data = "Speed" == anchorLabels[anchor.identifier]! ? nearData : farData
let base = "Speed" == anchorLabels[anchor.identifier]! ? 0.27 : 0.2 as Float
print ("Getting Node for: " + self.anchorLabels[anchor.identifier]!)
var count = 0.0 as Float
for dataItem in data {
    let transform = anchor.transform
    let label = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)


    let plane = SCNPlane(width: self.sceneView.bounds.width/2000, height: self.sceneView.bounds.height/2000/2)  //was sceneView

    label.update(dataItem.title!, andValue: dataItem.value!, withTrend: dataItem.trend)
    label.delegate = self

    plane.firstMaterial?.blendMode = .alpha
    plane.firstMaterial?.diffuse.contents = label.view //self.contentController?.view

    let planeNode = SCNNode(geometry: plane)
    planeNode.opacity = 0.75
    planeNode.simdPosition = float3(transform.columns.3.x + ( base * count), 0, transform.columns.3.z)
    node.addChildNode(planeNode)
    childControllers[label] = planeNode
    label.myNode = planeNode
    label.parentNode = node

    if("Speed" == anchorLabels[anchor.identifier]!) {
        let constraint = SCNBillboardConstraint()
        planeNode.constraints = [constraint]         
    } 
    count+=1
}

并更新

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

    guard currentBuffer == nil else {
        return
    }
    self.updateFocusSquare(isObjectVisible: false)
    // Retain the image buffer for Vision processing.
    self.currentBuffer = sceneView.session.currentFrame?.capturedImage
    classifyCurrentImage() 
}

ClassifyCurrentImage是条形码识别器所在的位置 . 如果找到条形码,则会在场景中的位置添加锚点 .