2015-10-29 8 views
5

Ho un metodo di supporto che si estende SKPhysicsContactdidBeginContact passato 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() Io chiamo questo metodo sul passato in contact.

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

ricevo questo messaggio di errore a volte (come 1 a 5), ​​che blocca l'applicazione:

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

Alzai gli occhi PKPhysicsContact ed è parte di un quadro privato (link). SKPhysicsContact sembra che sia solo una definizione di classe vuota che espone solo determinate proprietà di PKPhysicsContact.

Mi sembra che questo è un hack Objective-C sul team SpriteKit che interrompe la digitazione forte di Swift.

Aiuto?

Come assicurarsi di ottenere sempre SKPhysicsContact indietro?


ho aggiunto un controllo per verificare SKPhysicsContact

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

che cattura correttamente il tipo di mis-match.

Infatti, MAI restituisce un SKPhysicsContact !!?


Ho provato a farlo in Objective-C (come suggerito dal risponditore) e sto ottenendo lo stesso risultato.

Ho una discussione sullo Apple Dev Forums che potrebbe fornire un aiuto in futuro ai cercatori di risposte.

Ecco il codice Objective-C per riferimento:

@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 

dice qui,

-(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); 
    ... 

restituisce questo incidente:

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

Aggiunto Bug Report per Apple, # 23332190

+0

Dove è definito 'bodiesMatchingCategory'? È in un'estensione di 'SKPhysicsContact'? –

+0

@BenKane sì, è in cima alla mia domanda –

+0

Oh, wow. Non so come mi sia perso quello :) Comunque, vedi la mia risposta. Sono andato avanti con l'ipotesi che fosse così. –

risposta

5

ottengo lo stesso errore con questo semplice codice:

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) 

Il problema è che il tipo di contact è PKPhysicsContact (come hai notato), anche quando si esplicitamente dice di essere un SKPhysicsContact, e l'estensione è SKPhysicsContact. Dovresti essere in grado di creare un'estensione a PKPhysicsContact affinché funzioni. Da questa logica, possiamo dire che nessun metodo di istanza funzionerà nelle estensioni SKPhysicsContact al momento.Direi che è un bug con SpriteKit, e dovresti archiviare un radar. I metodi di classe funzionano ancora da quando li chiami sulla classe stessa.

Nel frattempo, dovresti essere in grado di spostare quel metodo nella scena o in un altro oggetto e chiamarlo lì con successo.


Per la cronaca, questo non è un problema Swift-specifica. Se si esegue lo stesso metodo in una categoria Objective-C su SKPhysicsContact, si verificherà lo stesso arresto anomalo.

+1

Per la cronaca, se metti 'let contact = SKPhysicsContact()' in un parco giochi, vedrai che il tipo restituito è 'PKPhysicsContact'. Quindi immagino che questo sia il vero problema. In realtà non è mai un "SKPhysicsContact" (come hai osservato), il che spiega perché il metodo di istanza non funziona, ma il metodo di classe. Sicuramente sembra un insetto. –

+1

@stephen Ora che ho visto la tua implementazione, ho eliminato il suggerimento func della classe, dato che non avresti accesso a bodyA e bodyB. Dovrai chiamare questo metodo da qualche altra parte (forse una scena, forse una classe di manager di fisica). Da quello che vedo, il tipo di SKPhysicsContact() è sempre 'PKPhysicsContact', anche se provi espressamente a lanciare, o dì che sia" SKPhysicsContact "in fase di assegnazione. Questo spiega perché il tuo metodo di estensione non funziona. Dovrebbe essere un'estensione su 'PKPhysicsContact', che non potrai fare AFAIK. –

+0

@stephen Ho modificato la mia risposta originale per avere effettivamente un senso e fornire una piccola spiegazione. Ho avuto qualche informazione negativa nell'originale, mi dispiace per quello. –

Problemi correlati