我希望获取属性属性的关键路径的值,例如size.width
的{{1}}或position.x
的值。如果我在SKSpriteNode
中有以下代码,则在最后一行出现运行时错误:
SKScene
在Swift 4中有没有办法做到这一点?任何帮助表示赞赏,并提前感谢。
修改
以下是另一个不起作用的例子:
let sprite = SKSpriteNode()
sprite.color = SKColor.red
sprite.size = CGSize(width: 50, height: 50)
sprite.position = CGPoint(x: 320, y: 240)
self.addChild(sprite)
print(sprite.value(forKeyPath: "position")) //NSPoint: {320, 204}
print(sprite.value(forKeyPath: "size")) //NSSize: {50,50}
print(sprite.value(forKeyPath: "position.x")) //terminating with uncaught exception of type NSException
我知道我可以做@Eric为我的第一个例子说的话:
class Object: NSObject {
var foo : Foo = Foo()
}
class Foo : NSObject {
var bar : Int = 0
}
let myObject = Object()
print(myObject.foo.bar) //0
print(myObject.value(forKeyPath: "foo.bar")) //terminating with uncaught exception of type NSException
但这在我的第二个例子中不起作用:
print((sprite.value(forKeyPath: "position") as! CGPoint).x) //works fine
这让我相信这是一个“ hack ”,它不会一直有效,所以我希望不要使用它。通过对这个主题的更多研究,我发现了这个Objective C代码,它表明了keyPath的值的全部要点是能够获得属性的属性:
print((myObject.value(forKeyPath: "foo") as! Foo).bar) //still terminating with uncaught exception of type NSException
如果我将其转换为swift,我会得到这个:
// Using nested valueForKey:
NSLog(@"%@", [[myObject valueForKey:@"foo"] valueForKey:@"bar"]);
// Can be done with a single valueForKeyPath;
NSLog(@"%@", [myObject valueForKeyPath:@"foo.bar"]);
第二行的简单修复:
// Using nested valueForKey:
print(myObject.value(forKey: "foo").value(forKey: "bar")) //Error: value of 'Any?' has no member 'value'
// Can be done with a single valueForKeyPath;
print(myObject.value(forKeyPath: "foo.bar")) //terminating with uncaught exception of type NSException
但是现在他们都显示错误,这让我相信这可能是关键字值和关键值forKey没有在swift中正确实现。如果有人能提供一点点煽动所有这些将是非常有帮助的。
答案 0 :(得分:1)
关于编辑部分。
通过KVC(基于字符串的keyPath使用KVC)访问的所有属性都需要暴露给Objective-C运行时。在Swift 4中,您需要使用class Object: NSObject {
@objc var foo : Foo = Foo() //<-
}
class Foo : NSObject {
@objc var bar : Int = 0 //<-
}
let myObject = Object()
print(myObject.foo.bar) //->0
print(myObject.value(forKeyPath: "foo.bar")) //->Optional(0)
print((myObject.value(forKey: "foo") as! Foo).value(forKey: "bar")) //->Optional(0)
print((myObject.value(forKeyPath: "foo") as! Foo).bar) //->0
明确注释。
let sprite = SKSpriteNode()
sprite.color = SKColor.red
sprite.size = CGSize(width: 50, height: 50)
sprite.position = CGPoint(x: 320, y: 240)
print(sprite[keyPath: \SKSpriteNode.position]) //->(320.0, 240.0)
print(sprite[keyPath: \SKSpriteNode.size]) //->(50.0, 50.0)
print(sprite[keyPath: \SKSpriteNode.position.x]) //->320.0
关于原始部分。
考虑使用Swift 4的smart KeyPath。
{{1}}
Smart KeyPath不是基于String的keyPath的另一种表示法,因此它无法替换KVC keyPaths的所有用例。但它可以使用非Objective-C属性,这在某些情况下非常方便。
答案 1 :(得分:0)
最后一行不会起作用,因为它现在没有正手#34;位置&#34;将是具有NSPoint
值的x
。为了使它工作,只需将位置转换为CGPoint/NSPoint
,如此:
print((sprite.value(forKeyPath: "position") as! CGPoint).x)
然而,硬拼接,解释标记的作用并不是一个好主意,因为当精灵没有设置位置时它会崩溃,所以它更好用:
if let position = sprite.value(forKeyPath: "position") as? CGPoint {
print(position.x)
}