Search code examples
iphoneiosuiviewcore-animation

Synchronizing UIView animations


Hi in response to touch events, my application does view animation. If the user is really fast and does another touch even while the current animation is happening then everything gets messed up.

Is there a standard way to handle this problem provided by the framework? Or am I doing the animation in a wrong way?

Currently it is checking a flag (animationInProgress) to handle this but I wanted to know if that is what we have to resort to for this?

Here is the code:

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    NSMutableArray *c = (NSMutableArray*)context;
    UINavigationController *nc = [c objectAtIndex:0];
    [nc.view removeFromSuperview];
    animationInProgress = NO;
}

- (void)transitionViews:(BOOL)topToBottom {
    if (animationInProgress) {
        return;
    }
    animationInProgress = YES;
    NSMutableArray *context = [[NSMutableArray alloc] init];
    [UIView beginAnimations:@"myanim" context:context];
    [UIView setAnimationDuration:0.7f];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    UIViewController *from;
    UIViewController *to;
    if (navController3.view.superview == nil ) {
        from = navController2;
        to = navController3;
    } else {
        from = navController3;
        to = navController2;
    }

    int height;
    if (topToBottom) { 
        height = -1 * from.view.bounds.size.height;
    } else {
        height = from.view.bounds.size.height;
    }

    CGAffineTransform transform = from.view.transform;

    [UIView setAnimationsEnabled:NO];
    to.view.bounds = from.view.layer.bounds;
    to.view.transform = CGAffineTransformTranslate(transform, 0, height);
    [window addSubview:to.view];

    [UIView setAnimationsEnabled:YES];
    from.view.transform = CGAffineTransformTranslate(from.view.transform, 0, -1 * height);
    to.view.transform = transform;

    [context addObject:from];

    [UIView commitAnimations];

    return;
}

Solution

  • The default behavior of the frameworks is, as you noticed, to allow anything to happen simultaneously if you want it to.

    Using a flag like you're doing is perfectly reasonable if your goal is to block a specific animation from happening if it's already running.

    If you want to go "up a level" conceptually and stop any touch events from entering your application at all during the animation, you can use:

    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    

    paired with a:

    [[UIApplication sharedApplication] endIgnoringInteractionEvents];