Swift: no se puede abatir AnyObject a SKPhysicsBody

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

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

Noté que devuelve una matriz de AnyObject. Así que leí sobre cómo lidiar con la conversión de AnyObject aquí.

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

Lo intenté primero:

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

Pero me sale este error.

error fatal: la matriz no se puede descender a una matriz de derivado

También probé esto:

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

Pero esto también se cuelga con lo siguiente:

introduzca la descripción de la imagen aquí

Y de manera similar, probé esto:

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

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

Y si no lanzo en absoluto, no me estrello. Por ejemplo:

 for object in self.physicsBody.allContactedBodies() { } 

Pero obviamente necesito lanzar si quiero usar el tipo real.

Entonces, como testing, acabo de probar esto:

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

Y esto también produce el mismo locking que se ve en la image.

Pero otros types no se bloquearán. Por ejemplo, esto no se bloqueará.

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

Entonces, mi pregunta es: ¿cómo puedo hacerlo correctamente a través de la matriz allContactedBodies ?

Edit: Estoy ejecutando Xcode 6 beta 4 en el dispositivo iOS 8 beta 4.

Edición 2: más información

Ok, así que acabo de hacer algunas testings más. He intentado esto:

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

Si "allContactedBodies" está vacío, entonces el reparto es exitoso. Pero si "allContactedBodies" contiene objects, entonces el yeso falla y "los cuerpos" se volverán nulos, así que no puedo pasar por él. Parece que actualmente NO es POSIBLE enviar AnyObject a SKPhysicsBody, por lo que es imposible hacer un recorrido por el set "allContactedBodies", a less que alguien pueda proporcionar una solución.

Editar 3: Bug todavía en Xcode 6 beta 5. La solución publicada a continuación sigue funcionando
Edición 4: Error aún en Xcode 6 beta 6. La solución publicada a continuación sigue funcionando
Edición 5: decepcionado. Error aún en Xcode 6 GM. La solución publicada a continuación sigue funcionando

EDIT 6: recibí el siguiente post de Apple:

Engineering ha proporcionado la siguiente información:

Creemos que este problema se abordó en la versión más reciente de Xcode 6.1 beta.

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

Edición 7: Xcode 6.3, aún no arreglado, la solución sigue funcionando.

Después de mucho ensayo y error, encontré una solución a mi problema. Resulta que no necesita abatirse en absoluto para acceder a las properties de SKPhysicsBody, cuando el tipo es AnyObject.

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

Actualización: Este fue un error y se solucionó en iOS 9 / OS X 10.11. El código como el siguiente debería funcionar ahora:

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

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


Me di count de esto en la barra lateral de preguntas relacionadas mientras respondía a esta , y resulta ser el mismo problema subyacente. Por lo tanto, mientras que Epic Byte tiene una solución viable , aquí está la raíz del problema, por qué la solución funciona y algunas más soluciones …

No es que no puedas convertir AnyObject a SKPhysicsBody en general; es que las cosas que se esconden detrás de estas references particulares de AnyObject no se pueden SKPhysicsBody a SKPhysicsBody .

La matriz devuelta por allContactedBodies() realidad contiene objects PKPhysicsBody , no objects SKPhysicsBody . PKPhysicsBody no es API pública, presumiblemente, se supone que es un detalle de implementación que no ves. En ObjC, es genial PKPhysicsBody * un PKPhysicsBody * a SKPhysicsBody * … "simplemente funcionará" siempre que SKPhysicsBody * solo methods que comparten las dos classs. Pero en Swift, puedes lanzar con as / as? / as! solo sube o baja la jerarquía de types, y PKPhysicsBody y SKPhysicsBody no son una class primaria y una subclass.

Obtiene un casting de error let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody porque incluso el inicializador SKPhysicsBody devuelve un PKPhysicsBody . La mayoría de las veces no necesita pasar por este baile (y hacerlo fallar), porque recupera un solo SKPhysicsBody de un inicializador o método que dice devolver un SKPhysicsBody : todo el molde ondulado a mano entre SKPhysicsBody y PKPhysicsBody está sucediendo en el lado ObjC y Swift confía en la API ObjC importada (y vuelve a llamar a la API original a través del time de ejecución ObjC, por lo que funciona igual que en ObjC a pesar de la falta de coincidencia de types).

Pero cuando lanzas una matriz completa, una tipografía en time de ejecución tiene que ocurrir en el lado Swift, por lo que las reglas de control de types más estrictas de Swift entran en juego … emitir una instancia de SKPhysicsBody a SKPhysicsBody falla esas reglas, por lo que se SKPhysicsBody . Puede convertir una matriz vacía en [SKPhysicsBody] sin error porque no hay objects de tipo conflictivo en la matriz (no hay ningún object en la matriz).

La solución de Byte de Epic funciona porque AnyObject de Swift funciona como el tipo de id de ObjC: el comstackdor le permite llamar a methods de cualquier class, y simplemente espere que en el time de ejecución esté tratando con un object que realmente implemente esos methods.

Puede recuperar un poco de security del tipo de compilation al forzar explícitamente un reparto lateral:

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

Después de esto, el body es un SKPhysicsBody , por lo que el comstackdor te permitirá llamar solo a los methods de SKPhysicsBody … este se comporta como el lanzamiento de ObjC, por lo que aún te quedas esperando que los methods que llamas sean realmente implementados por el object que estás Hablando a. Pero al less el comstackdor puede ayudarte a mantenerte honesto. (No se puede unsafeBitCast un tipo de matriz unsafeBitCast , por lo que debe hacerlo en el elemento, dentro del bucle).

Esto probablemente debería considerarse un error, por lo que le rogamos a Apple que sepa si le está afectando.