I have a helper method which extends SKPhysicsContact
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()
I call this method on the passed in contact
.
func didBeginContact(contact: SKPhysicsContact) {
let ballMask: UInt32 = 0x1 << 2
let ball = contact.bodiesMatchingCategory(ballMask)
...
I get this error message sometimes (like 1 in 5) which crashes the app:
-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x165f2350
I looked up PKPhysicsContact
and it's part of a private framework (link). SKPhysicsContact
looks like it's just an empty class definition which exposes only certain properties of PKPhysicsContact
.
I feel like this is an Objective-C hack on the SpriteKit team that breaks Swift's strong typing.
Help?
How to make sure I always get SKPhysicsContact
back?
I added a check to test for SKPhysicsContact
let test = contact as Any
print("Test is: \(test)")
guard test is SKPhysicsContact else {
return
}
Which correctly catches the type mis-match.
In fact, it NEVER returns a SKPhysicsContact
!!?
I've tried doing this in Objective-C (as suggested by responder) and I'm getting the same result.
I have a discussion on the Apple Dev Forums which may provide future answer-seekers some help.
Here's the Objective-C code for reference:
@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
Called Here:
-(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);
...
Returns this crash:
-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0'
Added Bug Report for Apple, #23332190