2015-10-29 7 views
5

ich eine Hilfsmethode haben, die SKPhysicsContactdidBeginContact bestanden PKPhyicsObject

extension SKPhysicsContact { 

    /// - returns: `[SKPhysicsBody]` containing all the bodies that match `mask` 
    func bodiesMatchingCategory(mask: UInt32) -> [SKPhysicsBody] { 
     let bodies = [bodyA, bodyB] 
     return bodies.filter { ($0.categoryBitMask & mask) != 0 } 
    } 
} 

in didBeginContact() erstreckt Ich nenne diese Methode auf dem in contact geben.

func didBeginContact(contact: SKPhysicsContact) { 
    let ballMask: UInt32 = 0x1 << 2 
    let ball = contact.bodiesMatchingCategory(ballMask) 
... 

Ich erhalte diese Fehlermeldung manchmal (wie 1: 5), die die App abstürzt:

-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x165f2350 

ich PKPhysicsContact nachgeschlagen und es ist Teil eines privaten Rahmen (link). SKPhysicsContact sieht aus wie es ist nur eine leere Klassendefinition, die nur bestimmte Eigenschaften von PKPhysicsContact offen legt.

Ich glaube, das ist ein Objective-C-Hack im SpriteKit-Team, der Swifts starke Typisierung durchbricht.

Hilfe?

Wie stelle ich sicher, dass ich immer SKPhysicsContact zurück bekomme?


habe ich einen Scheck für SKPhysicsContact

let test = contact as Any 
print("Test is: \(test)") 
guard test is SKPhysicsContact else { 
    return 
} 

zu testen, welche die Art mis-match richtig einrastet.

Tatsächlich ist es NIE gibt SKPhysicsContact zurück !!?

Ich habe versucht, dies in Objective-C (wie von Responder vorgeschlagen) und ich bekomme das gleiche Ergebnis.

Ich habe eine Diskussion über die Apple Dev Forums, die zukünftige Antwort-Sucher einige Hilfe bieten kann.

Hier ist die Objective-C-Code als Referenz:

@interface SKPhysicsContact (MatchingBodies) 

- (NSArray *)bodiesMatchingCategory:(UInt32)category; 

@end 

@implementation SKPhysicsContact (MatchingBodies) 

- (NSArray *)bodiesMatchingCategory:(UInt32)category { 
    NSArray *bodies = @[self.bodyA, self.bodyB]; 

    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(SKPhysicsBody *body, NSDictionary *bindings) { 
     return (body.categoryBitMask & category) != 0; 
    }]; 
    NSArray *matching = [bodies filteredArrayUsingPredicate:predicate]; 
    return matching; 
} 

@end 

hier genannt:

-(void)didBeginContact:(SKPhysicsContact *)contact 
{ 
    static const uint32_t MarbleContact = 0x1 <<1; // 2 
    static const uint32_t GoalContact = 0x1 <<2; // 4 

    SKPhysicsBody *ball = [contact bodiesMatchingCategory:MarbleContact].firstObject; 
    NSLog(@"Ball: %@", ball); 
    ... 

Rückgabe dieser Absturz:

-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0' 

hinzugefügt Bug Report für Apple, # 23332190

+0

Wo ist 'bodysMatchingCategory' definiert? Ist das eine Erweiterung von 'SKPhysicsContact'? –

+0

@BenKane ja, es ist an der Spitze meiner Frage –

+0

Oh, wow. Ich weiß nicht, wie ich das verpasst habe :) Wie auch immer, siehe meine Antwort. Ich ging davon aus, dass dies der Fall war. –

Antwort

5

ich den gleichen Fehler mit diesem einfachen Code zu erhalten:

extension SKPhysicsContact { 
    func bodiesMatchingCategory(mask: UInt32) -> [SKPhysicsBody] { 
     let bodies = [bodyA, bodyB] 
     return bodies.filter { ($0.categoryBitMask & mask) != 0 } 
    } 
} 

let contact = SKPhysicsContact() 
let body = contact.bodiesMatchingCategory(0) 

Das Problem ist, ist die Art der contactPKPhysicsContact (wie Sie bemerkt haben), auch wenn Sie es ausdrücklich sagen, ein SKPhysicsContact zu sein, und Die Erweiterung ist SKPhysicsContact. Sie müssten in der Lage sein, eine Erweiterung auf PKPhysicsContact zu machen, damit dies funktioniert. Aus dieser Logik können wir sagen, dass momentan keine Instanzmethoden in SKPhysicsContact Erweiterungen funktionieren.Ich würde sagen, es ist ein Bug mit SpriteKit, und Sie sollten ein Radar senden. Klassenmethoden funktionieren immer noch, da Sie sie in der Klasse selbst aufrufen.

In der Zwischenzeit sollten Sie in der Lage sein, diese Methode in Ihre Szene oder ein anderes Objekt zu verschieben und dort erfolgreich aufzurufen.


Für das Protokoll ist dies kein Swift-spezifisches Problem. Wenn Sie dieselbe Methode in einer Objective-C-Kategorie unter SKPhysicsContact ausführen, erhalten Sie den gleichen Absturz.

+1

Für den Rekord, wenn Sie setzen 'let contact = SKPhysicsContact()' in einen Spielplatz, der zurückgegebene Typ ist 'PKPhysicsContact'. Also ich denke, das ist das eigentliche Problem. Es ist eigentlich nie ein 'SKPhysicsContact' (wie Sie gesehen haben), was erklärt, warum die Instanzmethode nicht funktioniert, aber die Klassenmethode. Definitiv scheint wie ein Fehler. –

+1

@stephen Jetzt, da ich Ihre Implementierung gesehen habe, habe ich den Vorschlag der Klasse func herausgenommen, da Sie keinen Zugriff auf bodyA und bodyB haben würden. Sie müssen diese Methode woanders aufrufen (Szene vielleicht. Vielleicht eine Physik-Manager-Klasse). Von dem, was ich sehen kann, ist der Typ von SKPhysicsContact() immer "PKPhysicsContact", auch wenn Sie explizit versuchen zu casten, oder sagen Sie es bei der Zuweisung "SKPhysicsContact". Das erklärt, warum Ihre Erweiterungsmethode nicht funktioniert. Es müsste eine Erweiterung auf 'PKPhysicsContact' sein, die Sie nicht in der Lage sind, AFAIK zu machen. –

+0

@stephen Ich habe meine ursprüngliche Antwort so bearbeitet, dass sie einen Sinn ergibt und eine kleine Erklärung liefert. Hatte einige schlechte Infos im Original, sorry. –

Verwandte Themen