Update: This was一个错误,它已在 iOS 9 / OS X 10.11 中修复 - 问题中的代码现在可以正常工作。
为后人/使用旧版 SDK 等的人留下原始答案文本。
这看起来像一个错误 -你应该把它归档。很难说它应该被视为 SpriteKit bug 还是 Swift bug,但那是 Apple 的问题,而不是你的问题。 :)
如果您将代码粘贴到游乐场中,问题就很明显了——您的joint
实际上是一个PKPhysicsJointWeld
在幕后。这是一些应该是实现细节的内部类。在 ObjC 中这没有问题,因为在 C 中进行转换只是告诉编译器“相信我,这个指针实际上是一个SKPhysicsJoint
,所以让我在其上调用物理联合方法(而不是其他方法),并且没有人会更明智”。Swift 中的转换要求在转换的类型之间存在类型层次结构关系 - 并且PKPhysicsJointWeld
不是以下的子类型/子类SKPhysicsJoint
,所以转换失败。
您可以通过避免强制转换来解决此问题[SKPhysicsJoint]
:
for joint in nodeA.physicsBody!.joints {
// do something else here
}
这样,你就失去了一些类型安全性——joint
is an AnyObject
,就像 ObjC 的id
type 编译器允许您调用其上的任何方法。 (如果该对象没有实现该方法,它可能会在运行时失败。)但至少它可以运行。
进一步的解决方法:在循环内,您可以强制转换joint
to SKPhysicsJoint
。但由于该转换是跨类型层次结构的,因此您必须使用unsafeBitCast
:
for joint in nodeA.physicsBody!.joints {
let skJoint = unsafeBitCast(joint, SKPhysicsJoint.self)
// do stuff with skJoint
}
这会让你恢复一点编译时类型的“安全”,因为此后编译器将需要你做的任何事情skJoint
兼容SKPhysicsJoint
,但它本质上仍然是不安全的,因为它依赖于一些可能并不总是有效的运行时类型。你必须unsafeBitCast
再次到达特定的联合子类,而不知道它可能是哪个子类。 (再次,这是提交错误的好时机.)
(您可能会注意到,粘贴到游乐场时physicsWorld
也是一个内部类:PKPhysicsWorld
。那么为什么这也不会失败呢?当您使用physicsWorld
属性,所有类型转换都发生在 ObjC 端,并且 Swift 信任 ObjC 告诉它的任何内容。当你处理joints
但是,您必须在 Swift 端进行类型转换,并且 Swift 对于类型检查更加严格。)