Animation Sometimes Doesn't Occur

2019-09-01 03:11发布

问题:

I am building a concentration-like game. The tiles get flipped by a button press. I then check to see if two tiles are flipped. When I don't do the check, the tiles flip as expected. When I do the check, the first tile flips correctly. If the second tile matches the first tile, sometimes the second tile doesn't do its flip animation before they both do their disappear animation.

-(void)twoTilesFlipped {

NSInteger i = 0;
for (i = 0; i < [bottomLayers count]; i++)
{
    if ([[flippedStatus objectAtIndex:i] isEqualToString: @"flipped"]) 
    {
        CALayer *tileOne = [bottomLayers objectAtIndex:i];
        NSInteger y = 0;
        for (y = 0; y < [bottomLayers count]; y++) 
        {
            if (y == i) 
            {
                continue;
            }

            if ([[flippedStatus objectAtIndex:y] isEqualToString: @"flipped"])

            {
                CALayer *tileTwo = [bottomLayers objectAtIndex:y];
                if (tileOne.contents == tileTwo.contents) {
                    _matchLabel.text = @"It's a match!";
                    [self disappearTheTiles:tileOne :tileTwo :i :y];
                    [self isGameOver];
                } else {
                    _matchLabel.text = @"Not a match!";
                    [self flipTheTilesBack:i :y];
                }
            }
        } return;

    }
}}

I am new to iOS programming (and programming in general (sort of)).

Oh, here is the method for flipping the tiles:

- (void)flipTiles:(UIButton *)buttonPressed {
int b = buttonPressed.tag;

CALayer *top = [topLayers objectAtIndex:b];
CALayer *bot = [bottomLayers objectAtIndex:b];

if ([[flippedStatus objectAtIndex:b] isEqualToString: @"flipped"]) 
{
    top = [bottomLayers objectAtIndex:b];
    bot = [topLayers objectAtIndex:b];
}

CAAnimation *topAnimation = [self flipAnimationWithDuration:0.75f forLayerBeginningOnTop:YES scaleFactor:0.75f];
CAAnimation *bottomAnimation = [self flipAnimationWithDuration:0.75f forLayerBeginningOnTop:NO scaleFactor:0.75f];

CGFloat zDistance = 1500.0f;
CATransform3D perspective = CATransform3DIdentity; 
perspective.m34 = -1. / zDistance;
top.transform = perspective;
bot.transform = perspective;

topAnimation.delegate = self;
[CATransaction begin];
[top addAnimation:topAnimation forKey:@"buttonPressed"];
[bot addAnimation:bottomAnimation forKey:@"buttonPressed"];

[CATransaction commit];
if ([[flippedStatus objectAtIndex:b] isEqualToString: @"notFlipped"]) {
    [flippedStatus replaceObjectAtIndex:b withObject:[NSString stringWithFormat:@"flipped"]];
} else {
    [flippedStatus replaceObjectAtIndex:b withObject:[NSString stringWithFormat:@"notFlipped"]];
}
//NSLog(@"And if we got here, why didn't it flip? Huh?!");}

The log prints, yet sometimes the tile doesn't flip before it does the disappear animation.

I am trying to be as clear as possible, but I can't get my mind around why it works sometimes and not other times. I think it has something to do with the "for" loops and the nested "ifs" but I don't understand why the animation doesn't happen especially since the NSLog always shows up in the console...

I have looked at a lot of animation related questions here and on other sites - read a number of animation sections in books and tutorials, but so far, nothing leaps out as an answer. I can, of course, provide the entire project if anyone needs that to look at...

I have tried adding time intervals in strategic places, to no avail. I have also tried tracking the flipped status of the tiles and that doesn't seem to work. Is there a way in -animationDidStop to tell if the second tile has completed its flip? I guess what I am asking is, is there a way to name a CAAnimation (like there is for a UIViewAnimation) so that I can tell if a specific animation completed? (Yes there is - key-value coding does the trick nicely!)

With some help from Bill, I have now started key code tagging the animations. Turns out the the animation does play, but after the disappear animation - which isn't what I need to have happen. So I need to put in some sort of check to make sure both flips have happened before letting the disappear animation happen. Any thoughts appreciated!

After adding more tracking, it seems that the disappear animation is happening before the flip animation - but only sometimes. The challenging part for me is figuring out how to tell the disappear animation to only happen after both of the flip animations have occurred. Working on it! Suggestions still encouraged!

回答1:

I kept trying things and finally did this:

-(void)buttonPressed: (UIButton*)buttoni 
{
    [self flipTiles:(UIButton *)buttoni];
    [NSTimer scheduledTimerWithTimeInterval:2.0
                                     target:self
                                   selector:@selector(twoTilesFlipped)
                                   userInfo:nil
                                    repeats:NO];
}

Instead of mucking about other places, I put the timer in this method and it seems to work. Of course a few other things aren't working now, but I think that is just tweaking! Thank you!