Ste*_*ani 5 interop ios sprite-kit skphysicscontact swift
我有一个扩展的帮助方法 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 }
}
}
Run Code Online (Sandbox Code Playgroud)
在didBeginContact()我呼吁在过了这个方法contact.
func didBeginContact(contact: SKPhysicsContact) {
let ballMask: UInt32 = 0x1 << 2
let ball = contact.bodiesMatchingCategory(ballMask)
...
Run Code Online (Sandbox Code Playgroud)
我有时会收到此错误消息(如5中的1),这会导致应用程序崩溃:
-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x165f2350
Run Code Online (Sandbox Code Playgroud)
我查了一下PKPhysicsContact,它是私人框架(链接)的一部分. SKPhysicsContact看起来它只是一个空的类定义,它只暴露了某些属性PKPhysicsContact.
我觉得这是SpriteKit团队的一个Objective-C黑客攻击,打破了Swift强大的打字.
救命?
如何确保我总是SKPhysicsContact回来?
我添加了一张支票来测试 SKPhysicsContact
let test = contact as Any
print("Test is: \(test)")
guard test is SKPhysicsContact else {
return
}
Run Code Online (Sandbox Code Playgroud)
哪个正确捕获类型不匹配.
事实上,它永远不会返回SKPhysicsContact!!?
我已尝试在Objective-C中执行此操作(由响应者建议)并且我得到相同的结果.
我对Apple Dev论坛进行了讨论,可能为未来的求职者提供一些帮助.
这是Objective-C代码供参考:
@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
Run Code Online (Sandbox Code Playgroud)
叫这里:
-(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);
...
Run Code Online (Sandbox Code Playgroud)
返回此崩溃:
-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x17dad9e0'
Run Code Online (Sandbox Code Playgroud)
添加了Apple的Bug Report,#23332190
我用这个简单的代码得到了同样的错误:
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)
Run Code Online (Sandbox Code Playgroud)
问题是,即使你明确地告诉它是一个,并且扩展已经开启,你的注意类型contact是PKPhysicsContact(正如你所注意到的).您必须能够进行扩展才能使其正常工作.从这个逻辑来看,我们可以说目前没有任何实例方法可以在扩展中工作.我说这是SpriteKit的一个错误,你应该提交雷达.类方法仍然有效,因为您在类本身上调用它们.SKPhysicsContactSKPhysicsContactPKPhysicsContactSKPhysicsContact
在此期间,您应该能够将该方法移动到场景或其他对象中并成功调用它.
为了记录,这不是特定于Swift的问题.如果在Objective-C类别中使用相同的方法,SKPhysicsContact则会发生相同的崩溃.