我定义了以下子类,其主要属性链接到枚举:
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)
工作正常,但是当我选择其中一个节点并尝试使用
更改其颜色属性时// node selection...
var geom = node.geometry! as! Sphere
geom.color.rawValue = 5
我得到“无法分配给这个表达式的结果”错误,但是我没有将color属性声明为常量,并且不明白为什么会发生这种情况。我假设我在相对于Sphere类的代码中犯了一些基本错误,对于这可能是什么想法?
编辑:使用
geom.color = SphereColor(rawValue: 5)!
正如Martin R所说,允许我构建并运行我的代码但是球体的颜色没有改变,这让我觉得我的子类声明仍然有问题。
答案 0 :(得分:1)
rawValue
是只读属性,您无法分配新值
它。您必须从中创建SphereColor
原始值并将其分配给color
属性:
geom.color = SphereColor(rawValue: 5)!
或者如果任何机会原始值可能超出范围 并且不存在匹配的颜色:
if let color = SphereColor(rawValue: 5) {
geom.color = color
}
答案 1 :(得分:0)
支持@MartinR修复第一个问题,但我对其余部分的回答太大而无法发表评论。
如上所述,rawValue
是枚举的只读属性。枚举为value types,因此您无法更改"实例"的值在枚举中,您创建了一个新值。 (将枚举想象成奇特的数字。你不能将7 本身改为另一个数字,你改变一个保持值为7的变量来保存另一个值。)从相应的值创建一个枚举值原始类型,使用init(rawValue:)
初始值设定项。
您的第二个问题是您正在更新模型(以概念/语义方式告诉您您认为您的球是什么颜色的部分),但您要重新设置该模型的视觉表示(只有在创建Sphere
时,才能看到SceneKit的东西),而不是在设置color
属性时。如果你想让模型和视图保持同步,你需要做到这一点。
您已经拥有在初始化程序中将Color
转换为SceneKit材质颜色的代码。因为您可以从其他地方调用它,然后您可以在模型更改时使用它来更新您的视图 - 例如,使用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) { /* ... */ }
}