1

以下代码给出了错误 - 物理关节数组似乎具有 PKPhysicsJoint 类。任何人都知道如何在 Swift 中迭代关节?

文档确实说physicsBody.joints 应该返回一个SKPhysicsJoint 数组。

import SpriteKit

let scene = SKScene(size: CGSize(width: 200, height: 200))
let nodeA = SKNode()
let nodeB = SKNode()

nodeA.physicsBody = SKPhysicsBody(circleOfRadius: 20)
nodeB.physicsBody = SKPhysicsBody(circleOfRadius: 20)

scene.addChild(nodeA)
scene.addChild(nodeB)

let joint = SKPhysicsJointFixed.jointWithBodyA(nodeA.physicsBody, bodyB: nodeB.physicsBody, anchor: CGPointZero)
scene.physicsWorld.addJoint(joint)

for joint in nodeA.physicsBody!.joints as [SKPhysicsJoint] {
  // do something else here
}

给出错误:

Execution was interrupted. reason: EXC_BAD_INSTRUCTION...
4

1 回答 1

3

更新:这一个错误,已在 iOS 9 / OS X 10.11 中修复——问题中的代码现在可以正常工作。

为后代/使用较旧 SDK 的人/等留下原始答案文本。


这看起来像一个错误——你应该把它归档。很难说它应该被认为是 SpriteKit 错误还是 Swift 错误,但这是 Apple 的问题,而不是你的问题。:)

如果您将代码粘贴到操场上,问题就很明显了——您joint实际上是PKPhysicsJointWeld在幕后。那是一些应该是实现细节的内部类。在 ObjC 中这没问题,因为在 C 中进行转换只是告诉编译器,“相信我,这个指针真的是SKPhysicsJoint一个更聪明”。在 Swift 中进行类型转换要求被转换类型之间存在类型层次关系——并且PKPhysicsJointWeld不是 的子类型/子类SKPhysicsJoint,因此类型转换失败。

您可以通过避免强制转换来解决此问题[SKPhysicsJoint]

for joint in nodeA.physicsBody!.joints {
    // do something else here
}

有了这个,你失去了一些类型安全——joint是一个AnyObject,所以就像 ObjC 的id类型一样,编译器允许你调用它的任何方法。(如果该对象没有实现该方法,它可能会在运行时失败。)但至少它运行。

进一步的解决方法:在循环内,您可以强制joint转换为SKPhysicsJoint. 但由于该转换跨越类型层次结构,因此您必须使用unsafeBitCast

for joint in nodeA.physicsBody!.joints {
    let skJoint = unsafeBitCast(joint, SKPhysicsJoint.self)
    // do stuff with skJoint
}

这让你回到了一点编译时类型的“安全性”,因为此后编译器将要求你所做的任何事情skJointSKPhysicsJoint可能并不总是成立。而且您必须unsafeBitCast再次到达特定的联合子类,而不知道它可能是哪个子类。(同样,这将是提交错误的好时机。)


(你可能会从粘贴到一个physicsWorld内部类的 Playground 中注意到:PKPhysicsWorld。那么为什么这也不会失败?当你使用该physicsWorld属性时,所有类型转换都发生在 ObjC 端,并且 Swift 信任任何 ObjC告诉它。但是,当您处理joints数组时,您必须在 Swift 端进行类型转换,而 Swift 对类型检查要严格得多。)

于 2015-02-13T18:08:52.083 回答