【问题标题】:Cannot convert value of type '[String : Any]?' to expected argument type 'Float'无法转换类型“[String:Any]?”的值到预期的参数类型'Float'
【发布时间】:2021-09-02 06:53:22
【问题描述】:

我正在尝试进行除法计算以放大或缩小我的 AR 项目的节点。但是我遇到了Cannot convert value of type '[String : Any]?' to expected argument type 'Float'的编译错误。

我知道会发生错误,因为 number 是一个可选参数,我尝试了几种不同的方法,但无法将它解包为 float 类型。这个要怎么拆?

guard let touchPositionInFrontOfCamera = getPosition(ofPoint: indexTip2, atDistanceFromCamera: self.distance, inView: self.sceneView) else { return }

for node in sceneView.scene.rootNode.childNodes{
    let distance = SCNVector3(
        touchPositionInFrontOfCamera.x - node.position.x,
        touchPositionInFrontOfCamera.y - node.position.y,
        touchPositionInFrontOfCamera.z - node.position.z
    )
    let radius: Float = sqrtf(distance.x * distance.x + distance.y * distance.y + distance.z * distance.z)
    print(node.geometry?.dictionaryWithValues(forKeys: ["radius"]), radius)
    let number = node.geometry?.dictionaryWithValues(forKeys: ["radius"])
    print(radius / number)
}

【问题讨论】:

  • print(node.geometry?.dictionaryWithValues(forKeys: ["radius"]), radius) 打印什么? @tonywang
  • 输出示例Optional(["radius": 0.382940411567688])
  • 你为什么打电话给NSObject.dictionaryWithValues(forKeys:)
  • @Alexander 因为我需要实时创建一个球体,除非我使用这种方法检查它,否则我不知道它的半径
  • 这不是你想要的方法。看我的回答。

标签: swift optional arkit


【解决方案1】:

dictionaryWithValues(forKeys 返回[String:Any] 你不能用Float 进行除法

guard let res = node.geometry?.dictionaryWithValues(forKeys: ["radius"]), let number = res["radius"] as? Float else { return } 
print(radius / number)

顺便说一句,根据你的几何形状,你可以很容易地看到半径

if let sphere = node.geometry as? SCNSphere { 
    print(sphere.radius) 
}

【讨论】:

    【解决方案2】:

    你走错了路。方法NSObject.dictionaryWithValues(forKeys:) 存在明确目的,即根据接收者对象的属性值(对于给定的属性名称)制作字典。你已经提出了这个要求,现在你想知道“我如何摆脱这个字典的东西?”。

    答案很简单:首先,不要制作你需要的字典!直接访问该属性即可。

    在这种情况下,它只是有点棘手,因为SCNNode.geometry 返回一个通用的SCNGeometry 类型,它没有半径(想想,如果它是一个立方体,它的半径是多少?这是无意义的) .所以在这种情况下,您需要将一般的SCNGeometry 类型缩小为更窄的类型,可能是SCNSphere

    for node in sceneView.scene.rootNode.childNodes {
        let distance = SCNVector3(
            touchPositionInFrontOfCamera.x - node.position.x,
            touchPositionInFrontOfCamera.y - node.position.y,
            touchPositionInFrontOfCamera.z - node.position.z
        )
        let radius: Float = sqrtf(distance.x * distance.x + distance.y * distance.y + distance.z * distance.z)
        let number = (node.geometry as? SCNSphere).radius
        print(number, radius)
        print(radius / number)
    }
    

    这里还有很多样板,你应该自己做一些辅助函数和操作符来清理它:

    extension SCNVector3 {
        func distance(to target: other) -> SCNFloat {
            (target - self).magnitude()
        }
    
        static func - (a: SCNVector3, b: SCNVector3) -> SCNVector3 {
            SCNVector3(a.x - b.x, a.y + b.y, a.z + b.z)
        }
    
        var magnitude: SCNFloat {
            (x*x + y*y + z*z).squareRoot()
        }
    }
    
    for node in sceneView.scene.rootNode.childNodes {
        guard let sphere = (node.geometry as? SCNSphere) else {
           // FIXME: the geometry wasn't a sphere, after all! Handle it.
           fatalError()
        }
    
        let radius = node.distance(to: touchPositionInFrontOfCamera)
        let number = sphere.radius
        print(number, radius, radius / number)
    }
    

    看看这变得多么简单。

    【讨论】:

    • 我选择了这个答案,因为它提供了最详细的解释。
    猜你喜欢
    • 2019-09-15
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多