Frage

Apple verfügt über die folgende Methode in der SKPhysicsBody-Klasse.

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

Mir ist aufgefallen, dass es ein Array von AnyObject zurückgibt.Also habe ich gelesen, wie man mit dem Downcasting von AnyObject umgeht Hier

Ich möchte das Array allContactedBodies meines Physikkörpers durchlaufen.Das Problem ist, egal was ich versuche, ich schaffe es einfach nicht, etwas zum Laufen zu bringen.

Ich habe es als erstes versucht:

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

}

Aber ich bekomme diesen Fehler.

fataler Fehler:Das Array kann nicht auf ein abgeleitetes Array heruntergestuft werden

Ich habe auch Folgendes versucht:

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

Dies stürzt aber auch mit Folgendem ab:

enter image description here

Und ähnlich habe ich Folgendes versucht:

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

 }

Es gibt keinen Absturz, aber „Körper“ wird zu Null.

Und wenn ich überhaupt nicht wirke, bekomme ich keinen Absturz.Zum Beispiel:

for object in self.physicsBody.allContactedBodies()  {

}

Aber natürlich muss ich umwandeln, wenn ich den tatsächlichen Typ verwenden möchte.


Als Test habe ich dann einfach Folgendes ausprobiert:

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

Und dies führt auch zu dem gleichen Absturz, der auf dem Bild zu sehen ist.


Aber andere Typen werden nicht abstürzen.Dies wird beispielsweise nicht abstürzen.

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

Meine Frage ist also: Wie kann ich das Array allContactedBodies korrekt durchlaufen??

Bearbeiten:Ich verwende Xcode 6 Beta 4 auf einem iOS 8 Beta 4-Gerät.

Bearbeiten 2:Mehr Informationen

Ok, also habe ich einfach noch ein paar Tests gemacht.Ich habe Folgendes versucht:

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

Wenn „allContactedBodies“ leer ist, ist die Umwandlung erfolgreich.Aber wenn „allContactedBodies“ Objekte enthält, schlägt die Umwandlung fehl und „bodies“ wird zu Null, sodass ich sie nicht durchlaufen kann.Es scheint, dass es derzeit einfach NICHT MÖGLICH ist, AnyObject in SKPhysicsBody umzuwandeln, was es unmöglich macht, das Array „allContactedBodies“ zu durchlaufen, es sei denn, jemand kann eine Problemumgehung bereitstellen.

Bearbeiten 3:Fehler immer noch in Xcode 6 Beta 5.Die unten angegebene Problemumgehung funktioniert weiterhin
Bearbeiten 4:Fehler immer noch in Xcode 6 Beta 6.Die unten angegebene Problemumgehung funktioniert weiterhin
Bearbeiten 5:Enttäuscht.Fehler immer noch in Xcode 6 GM.Die unten angegebene Problemumgehung funktioniert weiterhin

EDIT 6:Ich habe die folgende Nachricht von Apple erhalten:

Engineering hat die folgenden Informationen bereitgestellt:

Wir glauben, dass dieses Problem in der neuesten Betaversion von Xcode 6.1 behoben wurde.

ABER DAS IST ES NICHT, der Fehler ist immer noch in Xcode 6.1.1!!!Die Problemumgehung funktioniert immer noch.

Bearbeiten 7: Xcode 6.3, immer noch nicht behoben, Problemumgehung funktioniert immer noch.

War es hilfreich?

Lösung

Nach viel Prozess und Irrtum habe ich ein Problemumgeheimnis zu meinem Problem gefunden.Es stellt sich heraus, dass Sie überhaupt nicht deaktiviert werden müssen, um auf die Eigenschaften des KKPhysikbodys zuzugreifen, wenn der Typ anyObject ist.

generasacodicetagpre.

Andere Tipps

Aktualisieren:Dies war ein Fehler und wurde in iOS 9 / OS X 10.11 behoben.Code wie der folgende sollte jetzt funktionieren:

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

Hinterlassen des ursprünglichen Antworttextes für die Nachwelt / für Leute, die ältere SDKs verwenden / usw.


Das ist mir bei der Beantwortung in der Seitenleiste mit den entsprechenden Fragen aufgefallen Dieses hier, und es stellt sich heraus, dass es sich um dasselbe zugrunde liegende Problem handelt.Also, während Epic Byte hat einen praktikablen Workaround, hier ist die Ursache des Problems, warum die Problemumgehung funktioniert und einige weitere Problemumgehungen ...

Es ist nicht so, dass man nicht wirken kann AnyObject Zu SKPhysicsBody im Allgemeinen – es ist das/die Ding(e), das/die sich hinter diesen besonderen Dingen verbirgt AnyObject Verweise können nicht umgewandelt werden SKPhysicsBody.

Das von zurückgegebene Array allContactedBodies() tatsächlich enthält PKPhysicsBody Objekte, nicht SKPhysicsBody Objekte. PKPhysicsBody ist keine öffentliche API – vermutlich handelt es sich um ein Implementierungsdetail, das Sie nicht sehen.In ObjC ist es total cool, einen zu wirken PKPhysicsBody * Zu SKPhysicsBody *...es wird „einfach funktionieren“, solange Sie nur Methoden aufrufen, die die beiden Klassen zufällig gemeinsam nutzen.Aber in Swift können Sie mit casten as/as?/as! nur nach oben oder unten in der Typhierarchie und PKPhysicsBody Und SKPhysicsBody sind keine übergeordnete Klasse und Unterklasse.

Sie erhalten einen Casting-Fehler let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody denn sogar die SKPhysicsBody Initialisierer gibt a zurück PKPhysicsBody.In den meisten Fällen ist es nicht nötig, diesen Tanz zu absolvieren (und scheitern zu lassen), denn man bekommt einen einzigen SKPhysicsBody zurück von einem Initialisierer oder einer Methode, die behauptet, eine zurückzugeben SKPhysicsBody – der ganze handgewellte Guss dazwischen SKPhysicsBody Und PKPhysicsBody geschieht auf der ObjC-Seite und Swift vertraut der importierten ObjC-API (und ruft über die ObjC-Laufzeit die ursprüngliche API zurück, sodass es trotz der Typinkongruenz genauso funktioniert wie in ObjC).

Wenn Sie jedoch ein ganzes Array umwandeln, muss auf der Swift-Seite eine Laufzeittypumwandlung erfolgen, sodass die strengeren Typprüfungsregeln von Swift ins Spiel kommen ...Casting a PKPhysicsBody Instanz zu SKPhysicsBody verstößt gegen diese Regeln, sodass Sie abstürzen.Sie können ein leeres Array umwandeln [SKPhysicsBody] ohne Fehler, da das Array keine Objekte widersprüchlichen Typs enthält (es gibt keine). beliebig Objekte im Array).

Problemumgehung von Epic Byte funktioniert, weil Swift's AnyObject Funktioniert wie ObjCs id Typ:Mit dem Compiler können Sie Methoden jeder beliebigen Klasse aufrufen und hoffen, dass Sie es zur Laufzeit mit einem Objekt zu tun haben, das diese Methoden tatsächlich implementiert.

Sie können ein wenig Typsicherheit zur Kompilierungszeit wiederherstellen, indem Sie explizit eine Seitenumwandlung erzwingen:

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

Danach, body ist ein SKPhysicsBody, sodass der Compiler nur Sie aufrufen lässt SKPhysicsBody Methoden dazu...Dies verhält sich wie ein ObjC-Casting, sodass Sie immer noch hoffen müssen, dass die von Ihnen aufgerufenen Methoden tatsächlich von dem Objekt implementiert werden, mit dem Sie sprechen.Aber zumindest kann der Compiler dabei helfen, ehrlich zu bleiben.(Das kannst du nicht unsafeBitCast ein Array-Typ, daher müssen Sie dies mit dem Element innerhalb der Schleife tun.)

Dies sollte wahrscheinlich als Fehler betrachtet werden, also bitte lass es Apple wissen wenn es Sie betrifft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top