如何获取属性属性的关键路径的节点值

时间:2017-08-27 03:14:31

标签: swift properties key

我希望获取属性属性的关键路径的值,例如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中正确实现。如果有人能提供一点点煽动所有这些将是非常有帮助的。

2 个答案:

答案 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)
}