Pregunta

Apple tiene el siguiente método en la clase SKPhysicsBody.

 /* Returns an array of all SKPhysicsBodies currently in contact with this one */
    func allContactedBodies() -> [AnyObject]!

Noté que devuelve una matriz de AnyObject.Entonces leí sobre cómo lidiar con el lanzamiento de AnyObject. Aquí

Quiero recorrer la matriz allContactedBodies de mi cuerpo físico.El problema es que no importa lo que intento, simplemente no puedo hacer que las cosas funcionen.

Probé esto primero:

for body in self.physicsBody.allContactedBodies() as [SKPhysicsBody] {

}

Pero me sale este error.

error fatal:la matriz no se puede reducir a una matriz de derivados

También probé esto:

for object in self.physicsBody.allContactedBodies()  {
    let body = object as SKPhysicsBody
}

Pero esto también falla con lo siguiente:

enter image description here

Y de manera similar probé esto:

 for object in self.physicsBody.allContactedBodies()  {
     let body = object as? SKPhysicsBody

 }

No hay choque, pero el "cuerpo" se vuelve nulo.

Y si no lanzo nada, no me bloqueo.Por ejemplo:

for object in self.physicsBody.allContactedBodies()  {

}

Pero obviamente necesito emitir si quiero usar el tipo real.


Entonces, como prueba, probé esto:

let object: AnyObject = SKPhysicsBody()
let body = object as SKPhysicsBody

Y esto también resulta en el mismo bloqueo que se muestra en la imagen.


Pero otros tipos no fallarán.Por ejemplo, esto no fallará.

let object: AnyObject = SKNode()
let node = object as SKNode

Entonces mi pregunta es, ¿Cómo puedo recorrer correctamente la matriz allContactedBodies??

Editar:Estoy ejecutando Xcode 6 beta 4 en un dispositivo iOS 8 beta 4.

Edición 2:Más información

Ok, acabo de hacer algunas pruebas más.Probé esto:

let bodies = self.physicsBody.allContactedBodies() as? [SKPhysicsBody]

Si "allContactedBodies" está vacío, entonces la transmisión se realizó correctamente.Pero si "allContactedBodies" contiene objetos, entonces la conversión falla y "bodies" se volverá nulo, por lo que no puedo recorrerlo.Parece que actualmente NO ES POSIBLE enviar AnyObject a SKPhysicsBody, lo que hace imposible recorrer la matriz "allContactedBodies", a menos que alguien pueda proporcionar una solución alternativa.

Edición 3:Error aún en Xcode 6 beta 5.La solución alternativa publicada a continuación todavía funciona
Edición 4:Error aún en Xcode 6 beta 6.La solución alternativa publicada a continuación todavía funciona
Edición 5:Decepcionado.Error todavía en Xcode 6 GM.La solución alternativa publicada a continuación todavía funciona

EDITAR 6:He recibido el siguiente mensaje de Apple:

Ingeniería ha proporcionado la siguiente información:

Creemos que este problema se solucionó en la última versión beta de Xcode 6.1.

¡PERO NO LO ES, el error todavía está en Xcode 6.1.1!La solución todavía funciona.

Edición 7: Xcode 6.3, aún no solucionado, la solución alternativa aún funciona.

¿Fue útil?

Solución

Después de una gran prueba y error, he encontrado una workarlound a mi problema.Resulta que no necesita opcional para acceder a las propiedades del cuerpo skphysics, cuando el tipo es anyObject.

for object in self.physicsBody.allContactedBodies()  {
        if object.node??.name == "surface" {
            isOnSurface = true
        }
    }

Otros consejos

Actualizar:Esto fue un error y se solucionó en iOS 9/OS X 10.11.Código como el siguiente debería funcionar ahora:

for body in self.physicsBody.allContactedBodies()  {
    // inferred type body: SKPhysicsBody
    print(body.node) // call an API defined on SKPhysicsBody
}

Dejando el texto de respuesta original para la posteridad/personas que usan SDK más antiguos/etc.


Noté esto en la barra lateral de preguntas relacionadas mientras respondía Éste, y resulta ser el mismo problema subyacente.Entonces, mientras Epic Byte tiene una solución viable, aquí está la raíz del problema, por qué funciona la solución y algunas soluciones más...

No es que no puedas lanzar AnyObject a SKPhysicsBody en general, es que las cosas que se esconden detrás de estos AnyObject no se pueden enviar referencias a SKPhysicsBody.

La matriz devuelta por allContactedBodies() en realidad contiene PKPhysicsBody objetos, no SKPhysicsBody objetos. PKPhysicsBody no es una API pública; presumiblemente, se supone que es un detalle de implementación que no se ve.En ObjC, es genial lanzar un PKPhysicsBody * a SKPhysicsBody *..."simplemente funcionará" siempre que llame sólo a métodos que las dos clases comparten.Pero en Swift, puedes transmitir con as/as?/as! sólo hacia arriba o hacia abajo en la jerarquía de tipos, y PKPhysicsBody y SKPhysicsBody no son una clase padre ni una subclase.

Obtienes un error al transmitir let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody porque incluso el SKPhysicsBody El inicializador está devolviendo un PKPhysicsBody.La mayoría de las veces no necesitas pasar por este baile (y que falle), porque obtienes un solo SKPhysicsBody desde un inicializador o método que pretende devolver un SKPhysicsBody — todo el casting ondulado a mano entre SKPhysicsBody y PKPhysicsBody está sucediendo en el lado de ObjC, y Swift confía en la API de ObjC importada (y vuelve a llamar a la API original a través del tiempo de ejecución de ObjC, por lo que funciona tal como lo haría en ObjC a pesar de la discrepancia de tipos).

Pero cuando lanzas una matriz completa, es necesario que se produzca un encasillado en tiempo de ejecución en el lado de Swift, por lo que entran en juego las reglas más estrictas de verificación de tipos de Swift...lanzando un PKPhysicsBody instancia a SKPhysicsBody falla esas reglas, entonces te estrella.Puedes lanzar una matriz vacía para [SKPhysicsBody] sin error porque no hay ningún objeto de tipo conflictivo en la matriz (no hay cualquier objetos en la matriz).

La solución alternativa de Epic Byte funciona porque Swift AnyObject funciona como el de ObjC id tipo:el compilador te permite llamar a métodos de cualquier clase, y solo esperas que en tiempo de ejecución estés tratando con un objeto que realmente implemente esos métodos.

Puedes recuperar un poco de seguridad de tipos en tiempo de compilación forzando explícitamente una conversión lateral:

for object in self.physicsBody.allContactedBodies() {
    let body = unsafeBitCast(object, SKPhysicsBody.self)
}

Después de este, body es un SKPhysicsBody, por lo que el compilador le permitirá llamar sólo SKPhysicsBody métodos al respecto...esto se comporta como una conversión de ObjC, por lo que todavía tienes la esperanza de que los métodos que llamas realmente sean implementados por el objeto con el que estás hablando.Pero al menos el compilador puede ayudarle a ser honesto.(No puedes unsafeBitCast un tipo de matriz, por lo que debe hacerlo con el elemento, dentro del bucle).

Probablemente esto debería considerarse un error, así que por favor hazle saber a Apple si te está afectando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top