DidBeginContact passed PKPhyicsObject

I have a helper method that 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) ... 

Sometimes I get this error message (e.g. 1 out of 5) that causes the application to crash:

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

I looked at PKPhysicsContact and became part of a private framework ( link ). SKPhysicsContact looks like just an empty class definition that provides only specific PKPhysicsContact properties.

It seems to me that this is a hack of Objective-C in the SpriteKit team, which breaks the strict strict Swift configuration.

reference

How to make sure that I always get SKPhysicsContact back?


I added validation to validate SKPhysicsContact

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

What correctly catches the wrong type.

In fact, he NEVER returns SKPhysicsContact !!?


I tried to do this in Objective-C (as suggested by the responder), and I get the same result.

I have a discussion on the Apple Dev Forums that might help future searchers answer.

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 failure:

 -[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 error report for Apple # 23332190

+5
source share
1 answer

I get the same error with this simple code:

 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) 

The problem is that the contact type is PKPhysicsContact (as you noticed), even if you explicitly state that it is SKPhysicsContact and the extension is SKPhysicsContact . To do this, you will need to expand to PKPhysicsContact . From this logic, we can say that no instance methods will work in the SKPhysicsContact extensions at the moment. I would say that this is a bug with SpriteKit, and you should create a radar . Class methods still work, as you call them on the class itself.

In the meantime, you must transfer this method to your scene or other object and call it there successfully.


For the record, this is not a Swift related issue. If you make the same method in the Objective-C category on SKPhysicsContact , you will get the same failure.

+5
source

Source: https://habr.com/ru/post/1234820/


All Articles