SKScene runAction completion block not called

178 views Asked by At

I am working on a sprite kit game in which I have an action called playCountdown:

SKAction *playCountdown = [SKAction performSelector:@selector(startCountdown) onTarget:self];

playCountdown works fine but when it completes, the completion block never gets called.

[self runAction:playCountdown completion:^{
            NSLog(@"anything goes");
    }];

Here is startCountdown for completeness:

- (void)startCountdown{
    SKLabelNode *countdownLabel = [SKLabelNode labelNodeWithFontNamed:@"Arial"];

    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    __block short countdownValue = 3;

    countdownLabel.position = CGPointMake(screenWidth/2, screenHeight/2 - countdownLabel.fontSize/2);
    countdownLabel.zPosition = 100.0;
    countdownLabel.text = [NSString stringWithFormat:@"%d", countdownValue];
    countdownLabel.fontColor = [UIColor blackColor];
    countdownLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeBaseline;

    [self addChild:countdownLabel];

    SKAction *zoomIn = [SKAction scaleTo:1.5f duration:0.9];
    SKAction *fadeOut = [SKAction fadeAlphaTo:0.0f duration:0.1];
    SKAction *updateCount = [SKAction customActionWithDuration:0.0 actionBlock:^(SKNode *node, CGFloat elapsedTime) {
        SKLabelNode *textNode = (SKLabelNode *)node;
        countdownValue --;
        if (countdownValue == 0) {
            textNode.text = @"PLAY!";
        }
        else{
            textNode.text = [NSString stringWithFormat:@"%d", countdownValue];
        }

        textNode.alpha = 1.0f;
        textNode.xScale = 1.0f;
        textNode.yScale = 1.0f;
    }];

    SKAction *sequence = [SKAction sequence:@[zoomIn, fadeOut, updateCount]];
    SKAction *repeat = [SKAction repeatAction:sequence count:4];
    [countdownLabel runAction:repeat completion:^{
        [countdownLabel removeFromParent];
    }];

    NSLog(@"completed!");
}

I have verified that startCountdown actually reaches its end. However the completion block never gets called. Any ideas?

Thanks

2

There are 2 answers

1
sangony On

I would recommend you verify that your code is indeed being called by creating a very simple NSLog only block.

If you are still having problems, consider using a SKAction sequence instead. This will accomplish the same thing as you are trying to do with a completion block.

0
Don Miguel On

There must be an issue with a SKAction created using a selector... The code:

SKAction *playCountdown = [SKAction performSelector:@selector(startCountdown) onTarget:self];

would execute calling:

[self runAction:playCountdown completion:^{ ... }];

although the completion block would never get called.

I have instead created the playCountdown action using a block:

SKAction *playCountdown = [SKAction runBlock:^{
        [self startCountdown];
    }];

and the completion block now gets called. The problem now is that the end of the playCountdown action is not "understood" by the system and the 2 actions do not run serially but almost concurrently.