我有一个扩展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 }
    }
}

didBeginContact()中,我在传入的contact中调用此方法。
func didBeginContact(contact: SKPhysicsContact) {
    let ballMask: UInt32 = 0x1 << 2
    let ball = contact.bodiesMatchingCategory(ballMask)
...

有时,我会收到此错误消息(如5分之一),导致应用程序崩溃:
-[PKPhysicsContact bodiesMatchingCategory:]: unrecognized selector sent to instance 0x165f2350

我查找了PKPhysicsContact,它是私有(private)框架(link)的一部分。 SKPhysicsContact看起来像是一个空的类定义,仅暴露PKPhysicsContact的某些属性。

我觉得这是SpriteKit团队的Objective-C破解,破坏了Swift的强大输入能力。

帮助?

如何确保我总是能拿回SKPhysicsContact

我添加了一张支票以测试SKPhysicsContact
let test = contact as Any
print("Test is: \(test)")
guard test is SKPhysicsContact else {
    return
}

哪个正确捕获类型不匹配。

实际上,它从来没有返回SKPhysicsContact!?

我已经尝试在Objective-C中执行此操作(如响应者所建议),并且得到了相同的结果。

我对Apple Dev Forums进行了讨论,它可能会为将来的求职者提供一些帮助。

这是供引用的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

在这里叫:
-(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);
    ...

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

添加了针对Apple的错误报告#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)

问题是,即使您明确地将其指定为contact,并且扩展名在PKPhysicsContact上,SKPhysicsContact的类型也是SKPhysicsContact(如您所注意到的)。您必须能够扩展PKPhysicsContact才能起作用。根据这种逻辑,我们可以说目前没有实例方法在SKPhysicsContact扩展中将起作用。我想说这是SpriteKit的一个错误,您应该提交雷达。自从您在类本身上调用类方法以来,类方法仍然有效。

同时,您应该能够将该方法移至场景或其他对象中并在其中成功调用它。

记录下来,这不是特定于Swift的问题。如果在SKPhysicsContact的Objective-C类别中使用相同的方法,则将发生相同的崩溃。

关于ios - didBeginContact传递了PKPhyicsObject,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33422332/

10-10 09:02