"Cannot assign to the result of this expression" 变量 (var) 引起的错误

"Cannot assign to the result of this expression" error arising from a variable (var)

我定义了以下子class,其主要 属性 链接到一个枚举:

let NumberOfColors: UInt32 = 6

enum SphereColor: Int, Printable {
case Red = 0, Yellow, Blue, Green, Purple, White

var sphereName: String {
    switch self {
    case .Red:
        return "red"
    case .Yellow:
        return "yellow"
    case .Blue:
        return "blue"
    case .Green:
        return "green"
    case .Purple:
        return "purple"
    case .White:
        return "white"
    }
}

var description: String {
    return self.sphereName
}

static func random() -> SphereColor {
    return SphereColor(rawValue: Int(arc4random_uniform(NumberOfColors - 1)))!
    }
}


class Sphere: SCNSphere {
var color : SphereColor

init(radius: CGFloat, color: SphereColor) {
    self.color = color
    super.init()
    switch color.rawValue as Int {
    case 0:
        self.firstMaterial?.diffuse.contents = UIColor.redColor()
    case 1:
        self.firstMaterial?.diffuse.contents = UIColor.yellowColor()
    case 2:
        self.firstMaterial?.diffuse.contents = UIColor.blueColor()
    case 3:
        self.firstMaterial?.diffuse.contents = UIColor.greenColor()
    case 4:
        self.firstMaterial?.diffuse.contents = UIColor.purpleColor()
    case 5:
        self.firstMaterial?.diffuse.contents = UIColor.whiteColor()
    default:
        break
    }
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
    }
}

实例化使用

let sphere = Sphere(radius: radius, color: SphereColor.random()) 

let sphereNode = SCNNode(geometry: sphere)

工作正常,但是当我 select 其中一个节点并尝试将其颜色 属性 更改为

// node selection...
var geom = node.geometry! as! Sphere
geom.color.rawValue = 5

我收到 "Cannot assign to the result of this expression" 错误,但我没有将颜色 属性 声明为常量并且不明白为什么会这样。我假设我在与 Sphere class 相关的代码中犯了一些基本错误,关于这可能是什么的任何想法?

编辑:使用

geom.color = SphereColor(rawValue: 5)!

正如 Martin R 所说,允许我构建和 运行 我的代码,但球体的颜色没有改变,这让我觉得我的 subclass 声明仍然有问题.

rawValue 是只读的 属性,您不能分配新值 给它。您必须从 SphereColor 创建一个 原始值并将其分配给 color 属性:

geom.color = SphereColor(rawValue: 5)!

或者如果有 任何 可能原始值可能超出范围 并且不存在匹配的颜色:

if let color = SphereColor(rawValue: 5) {
    geom.color = color
}

支持@MartinR 解决第一个问题,但我对其余问题的回应太大而无法发表评论。

如前所述,rawValue 是枚举的只读 属性。枚举是 value types,因此您不会更改枚举的 "instance" 的值,而是创建一个新值。 (将枚举想象成花哨的数字。您不会将 7 本身 更改为另一个数字,而是将保存值 7 的变量更改为保存另一个值。)从相应的原始类型,使用 init(rawValue:) 初始值设定项。

你的第二个问题是你正在更新模型(以概念/语义的方式告诉你你认为你的球是什么颜色的部分)但是你正在设置该模型的视觉表示( SceneKit 的东西你可以看到)只有当你创建一个 Sphere 时,而不是当你设置它的 color 属性 时。如果你想保持模型和视图同步,你需要做到这一点。

您已经在初始化程序中拥有将 Color 转换为 SceneKit material 颜色的代码。考虑到这一点,这样您也可以从其他地方调用它,然后您可以在模型发生变化时使用它来更新您的视图——比如,使用 property observer.

除此之外还有一些其他改进:

class Sphere: SCNSphere {

    func setMaterialColor(sphereColor: SphereColor) {
        let color: UIColor
        // Switch on the enum, not the int.
        // That way the compiler can check exhaustiveness,
        // and you don't need a dead default case.
        switch sphereColor {
            case .Red:
                // Use a temporary for the color choice so 
                // you're only setting the material property once.
                color = UIColor.redColor()
            case .Yellow:
                color = UIColor.yellowColor()
            case .Blue:
                color = UIColor.blueColor()
            case .Green:
                color = UIColor.greenColor()
            case .Purple:
                color = UIColor.purpleColor()
            case .White:
                color = UIColor.whiteColor()
        }
        // Force-unwrap firstMaterial -- we "know" it should be non-nil,
        // so it's better to find out the hard way if something weird has happened.
        // (Either that or test the optional so you can manage failure specifically.)
        self.firstMaterial!.diffuse.contents = color
    }

    var color : SphereColor {
        didSet {
            self.setMaterialColor(color)
        }
    }

    init(radius: CGFloat, color: SphereColor) {
        self.color = color
        super.init()
        self.setMaterialColor(color)
    }

    required init(coder aDecoder: NSCoder) { /* ... */ }
}