【问题标题】:node.physicsBody.joints downcasting errornode.physicsBody.joints 向下转换错误
【发布时间】:2015-02-13 14:30:27
【问题描述】:

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

documentation 确实说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...

【问题讨论】:

  • 试试这个:for joint in nodeA.physicsBody!.joints { .. }

标签: swift sprite-kit skphysicsbody skphysicsjoint


【解决方案1】:

更新:这一个错误,它已在 iOS 9 / OS X 10.11 中修复 - 问题中的代码现在可以使用.

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


这看起来像一个错误 - you should file it。很难说它应该被认为是 SpriteKit 错误还是 Swift 错误,但这是 Apple 的问题,而不是你的问题。 :)

如果您将代码粘贴到 Playground 中,问题就很明显了 — 您的 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
}

这会让你恢复一点编译时类型的“安全性”,因为此后编译器将要求你对skJoint 所做的任何事情都与SKPhysicsJoint 兼容,但它本质上仍然是不安全的,因为它取决于在一些可能并不总是成立的运行时类型周围挥手致意。你必须再次unsafeBitCast 才能进入特定的联合子类,而不知道它可能是哪个子类。 (同样,this would be a good time to file a bug。)


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多