node.physicsBody.joints 向下转换错误 [英] node.physicsBody.joints downcasting error

查看:7
本文介绍了node.physicsBody.joints 向下转换错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code gives an error - it appears the physics joints array have the class PKPhysicsJoint. Anyone have any ideas how I can iterate through the joints in Swift?

documentation 确实说physicsBody.joints 应该返回一个SKPhysicsJoint 数组.

The documentation does say that physicsBody.joints should return an array of 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...

推荐答案

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

Update: This was a bug, and it's fixed in iOS 9 / OS X 10.11 — the code in the question just works now.

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

Leaving original answer text for posterity / folks using older SDKs / etc.

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

This looks like a bug — you should file it. Whether it should be considered a SpriteKit bug or a Swift bug is hard to say, but that's Apple's problem, not yours. :)

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

The problem is clear if you paste your code into a playground — your joint is actually a PKPhysicsJointWeld behind the scenes. That's some internal class that should be an implementation detail. In ObjC that's no problem, because casting in C is just a matter of telling the compiler, "trust me, this pointer is really an SKPhysicsJoint, so let me call physics joint methods (and nothing else) on it and and no one will be the wiser". Casting in Swift requires that there be a type hierarchy relationship between the casted types — and PKPhysicsJointWeld is not a subtype/subclass of SKPhysicsJoint, so the cast fails.

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

You can work around this issue by avoiding the cast to [SKPhysicsJoint]:

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

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

With this, you lose some type safety — joint is an AnyObject, so like ObjC's id type the compiler lets you call any method on it. (And it may fail at runtime if that object doesn't implement the method.) But at least it runs.

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

A further workaround: inside the loop, you can cast joint to SKPhysicsJoint. But since that cast is across the type hierarchy, you have to use unsafeBitCast:

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

这会让你回到一点编译时类型的安全",因为此后编译器将要求你对 skJoint 所做的任何事情都与 SKPhysicsJoint 兼容,但它本质上仍然是不安全的,因为它依赖于一些可能并不总是成立的运行时类型的手动操作.而且您必须再次unsafeBitCast 才能到达特定的联合子类,而不知道它可能是哪个子类.(同样,这是提交错误的好时机.)

This gets you back a little bit of compile-time type "safety", in that thereafter the compiler will require anything you do with skJoint to be compatible with SKPhysicsJoint, but it's still inherently unsafe in that it depends on some hand-waving around runtime types that may not always hold. And you have to unsafeBitCast again to get to a particular joint subclass, without knowing which subclass it might be. (Again, this would be a good time to file a bug.)

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

(You might notice from pasting into a playground that physicsWorld is of an internal class, too: PKPhysicsWorld. So why doesn't that fail, too? When you use the physicsWorld property, all the type casting happens on the ObjC side, and Swift trusts whatever ObjC tells it. When you deal with the joints array, though, you have to do a type cast on the Swift side, and Swift is much more strict about type checking.)

这篇关于node.physicsBody.joints 向下转换错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆