【问题标题】:Inout not working with SubClass object throws Cannot pass immutable value as inout argumentInout 不适用于 SubClass 对象抛出无法将不可变值作为 inout 参数传递
【发布时间】:2018-06-28 12:03:48
【问题描述】:

我有两个代码块

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
  // BLOCK 1 Which is not working 
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    var plane = Plane(with: planeAnchor) //IT IS SUBCLASS OF SCNNode
    var geo = plane.geometry
    plane.transform = SCNMatrix4MakeRotation(-.pi / 2, 1, 0, 0)

    update(&plane, withGeometry: plane.geo, type: .static)

   //Up here Cannot pass immutable value as inout argument: implicit conversion from 'Plane' to 'SCNNode' requires a temporary

    node.addChildNode(plane)

   // BLOCK 2 Which is working 


    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    let plane1 = SCNPlane(width: width, height: height)

    plane1.materials.first?.diffuse.contents = UIColor.white.withAlphaComponent(0.5)

    var planeNode = SCNNode(geometry: plane1)

    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x,y,z)
    planeNode.eulerAngles.x = -.pi / 2

    update(&planeNode, withGeometry: plane1, type: .static)
    // WORKING FINE

    node.addChildNode(planeNode)

    self.planes[anchor.identifier] = plane

}

BLOCK1

当我尝试将它的对象传递给需要inout 的函数时,我有子类class Plane: SCNNode 它显示错误

无法将不可变值作为 inout 参数传递:从“Plane”到“SCNNode”的隐式转换需要临时

如果我删除子类,那么它工作正常

为什么这是 swift bug 或者我遗漏了什么?

【问题讨论】:

    标签: swift arkit inout


    【解决方案1】:

    Inout 不适用于Subclass

    这里是例子

    class SuperClass {
        var name = "Prashant"
    
    }
    
    class TestObject:SuperClass {
    }
    
    
    func updateTemp ( object:inout SuperClass) {
        object.name = "P.T"
    }
    

    现在,当您创建 TestObject 的子类 SuperClass 对象时,将不允许这样做。

    var obj  = TestObject()
    self.updateTemp(object: &obj) // Cannot pass immutable value as inout argument: implicit conversion from 'TestObject' to 'SuperClass' requires a temporary
    print(obj.name)
    

    如何解决这个问题

    三种方式

    1) 使用var obj:SuperClass = TestObject()创建对象

    2) 这实际上不需要是inout,因为类是引用类型

    3) 创建类似的泛型函数(泛型很棒!!)

    func updateTemp<T:SuperClass> ( object:inout T) {
        object.name = "P.T"
    } 
    

    希望对大家有帮助

    【讨论】:

      【解决方案2】:

      由于 Plane 类是用“init(_anchor: ARPlaneAnchor)”初始化的,即使它被声明为 SCNNode 类,它也会返回与块 2 中的纯 SCNNode 不同的实例。

      我不是突变主题的专家,但我认为 Apple 博客中有一个有趣的文档 The Role of Mutation in Safety

      不太确定,但由于类本质上是可变的,您可能可以将更新函数移至 Plane 类作为(测试)解决方案

      【讨论】:

      • 感谢您的回答,但不是这样的!
      • 谢谢,我说过我不是专家,所以我应该找时间自己试试。但是哪一部分不是真的?你读过链接吗?
      • 由于 Plane 类是用“init(_anchor: ARPlaneAnchor)”初始化的,即使它被声明为 SCNNode 类,它也会返回与块 2 中的纯 SCNNode 不同的实例。 两者都是一样的,如果你创建其他类的子类,它的行为永远不会改变,就像创建超类实例一样
      • 嘿 Jose 我很抱歉,是的,你是对的 inout 它需要已定义的相同类对象。
      猜你喜欢
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多