EXC_BAD_ACCESS 8 行 spritekit 代码

EXC_BAD_ACCESS on 8 line spritekit code

我难以置信的短应用程序代码以某种方式产生了 EXC_BAD_ACCESS 错误。我已经在一个全新的应用程序上重现了这个错误。但我无法理解这是怎么发生的。

这是我的应用程序的完整代码(除了 xcode 为 spritekit 游戏自动生成的代码)。

-(void)didMoveToView:(SKView *)view {
    SKNode* pFirst = [SKNode node];
    [self addChild:pFirst];
    //
    SKSpriteNode* pSprite = [SKSpriteNode spriteNodeWithImageNamed:@"img61.png"];
    pSprite.centerRect = CGRectMake(0.4,0.4, 0.2, 0.2); // suspect 1
    pSprite.position = CGPointMake(0,0);
    pSprite.xScale = 2.0;
    pFirst.alpha = 0.0;             //  suspect 2
    //
    [pFirst addChild:pSprite];    
}

调试器将崩溃点放在这里:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

我怎样才能理解这里出了什么问题?

当然,这个问题最初来自一个更长的崩溃的应用程序。这是我简化后留下的代码,但保留了崩溃。

两行标记为"suspects"。令人惊讶的是,如果删除 suspect1 或 suspect2 中的任何一个,代码运行良好。完全看不懂

我们可以从centerRect,

的描述中找到一些线索

A property that defines how the texture is applied to the sprite.

因此,如果您设置精灵的 centerRect 并设置其 alpha = 0.0,则混合到帧缓冲区中的 alpha 将为 0(有关详细信息,请参阅 Creating a Textured Sprite)。从我们刚刚测试的当前案例来看,零 alpha 精灵被视为空精灵。所以给空精灵添加子节点会导致崩溃。

要解决这个问题,一种方法是把pFirst.alpha = 0.0;改成pFirst.hidden = YES;。另一种方法是在精灵渲染到场景后设置 alpha。在您的 didMoveToView 方法中,为 pFirst

分配标识符
pFirst.name = @"firstNode"

然后,在执行物理模拟后添加以下方法将 alpha 设置为零,

- (void)didSimulatePhysics
{
    [self enumerateChildNodesWithName:@"firstNode" usingBlock:^(SKNode *node, BOOL *stop) {
        if (node.alpha > 0.0) {
            node.alpha = 0.0;
        }
    }];
}