swift sprite-kit skphysicsbody skphysicsjoint

swift - node.physicsBody.joints error de downcasting



sprite-kit skphysicsbody (1)

Actualización : Esto fue un error, y está corregido en iOS 9 / OS X 10.11 - el código en la pregunta solo funciona ahora.

Dejar texto de respuesta original para la posteridad / personas que usan SDK anteriores / etc.

Esto parece un error: debes archivarlo . Si es un error de SpriteKit o un error de Swift es difícil de decir, pero ese es el problema de Apple, no el tuyo. :)

El problema está claro si pegas tu código en un patio de recreo: tu joint es en realidad una PKPhysicsJointWeld entre bastidores. Esa es una clase interna que debería ser un detalle de implementación. En ObjC eso no es problema, porque el casting en C es solo una cuestión de decirle al compilador, "confía en mí, este puntero es realmente un SKPhysicsJoint , así que déjame llamar a los métodos físicos de Física (y nada más) sobre él y nadie será el más sabio ". Casting en Swift requiere que exista una relación jerárquica de tipos entre los tipos casted, y PKPhysicsJointWeld no es un subtipo / subclase de SKPhysicsJoint , por lo que el lanzamiento falla.

Puede [SKPhysicsJoint] este problema evitando el [SKPhysicsJoint] a [SKPhysicsJoint] :

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

Con esto, pierdes algún tipo de seguridad: joint es un AnyObject , así que al igual que el id de ObjC, el compilador te permite llamar a cualquier método. (Y puede fallar en tiempo de ejecución si ese objeto no implementa el método). Pero al menos se ejecuta.

Otra solución alternativa: dentro del ciclo, puede lanzar una joint a SKPhysicsJoint . Pero como ese elenco está en la jerarquía de tipos, debes usar unsafeBitCast :

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

Esto te devuelve un poco de tipo de "seguridad" en tiempo de compilación, ya que a partir de entonces el compilador requerirá que todo lo que hagas con skJoint sea ​​compatible con SKPhysicsJoint , pero sigue siendo intrínsecamente inseguro ya que depende de algunas SKPhysicsJoint mano alrededor del tiempo de ejecución tipos que no siempre se mantienen. Y tiene que unsafeBitCast nuevamente para llegar a una determinada subclase conjunta, sin saber qué subclase podría ser. (De nuevo, este sería un buen momento para presentar un error ).

(Puede notar al pegar en un campo de juego que el mundo de physicsWorld es de una clase interna: PKPhysicsWorld . Entonces, ¿por qué eso no falla también? Cuando utiliza la propiedad physicsWorld , todo el tipo de lanzamiento ocurre en el lado ObjC, y Swift confía en lo que ObjC le diga. Sin embargo, cuando trabajas con la matriz de joints , tienes que hacer una conversión de tipo en el lado de Swift, y Swift es mucho más estricto con la comprobación de tipos.

El siguiente código da un error: parece que el conjunto de uniones físicas tiene la clase PKPhysicsJoint. Alguien tiene alguna idea de cómo puedo iterar a través de las articulaciones en Swift?

La documentación dice que physicsBody.joints debería devolver una matriz de 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 }

da error:

Execution was interrupted. reason: EXC_BAD_INSTRUCTION...