views:

555

answers:

1

I'm new to iPhone development and I'm trying to do a flip animation between a UIView and another UIView containing a regular UIView and a UIScrollView, the scroll view in turn has several UIViews as subviews.

Before the animation start, the scroll view needs to be offset to a particular point to show a particular subview (the user is jumping to a particular "chapter" in the scroll view).

It is animating fine, but the problem is that it will 'sometimes' (every third time perhaps) start the animation with one of the subviews of the scroll view instead of starting the animation with the original UIView ('overlayView' in the code below). I suspect this has to do with the fact that I set the offset of the scroll view before animating.

This is how I currently do it:

   // get the MPMoviePlayer window that has the views to animate between as subviews
   UIWindow *moviePlayerWindow = [[UIApplication sharedApplication] keyWindow];

    // tell the controller of the scroll view to set the scroll view offset
    [instructionControlsController setInstructionImageWithNumber:[self chapterAtTime:currentTime]];

    // Animate transition to instruction view
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.5];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView: moviePlayerWindow cache:NO];

    // the views to animate between
    [moviePlayerWindow sendSubviewToBack: overlayView];
    [moviePlayerWindow bringSubviewToFront: instructionControlsController.view];

    [UIView commitAnimations];

The setInstructionImageWithNumber method in the controller looks like this:

- (void) setInstructionImageWithNumber:(int)number
{
    if (number < kNumberOfPages)
     [scrollView setContentOffset: CGPointMake((number * kImageWidth), 0) animated:NO];
}

Any ideas of what I might be doing wrong and why I get this behavior where the animation looks fine sometimes and sometimes not?

A: 

What happens if you give the run loop a chance to update your view before beginAnimations? You might need to do this to give the view a chance to "catch up" and be accurately updated before animations start.

UIWindow *moviePlayerWindow = [[UIApplication sharedApplication] keyWindow];
[instructionControlsController setInstructionImageWithNumber:[self chapterAtTime:currentTime]];

//Before continuing the animation, let the views update
[self performSelector:@selector(continueTheAnimation:) withObject:nil afterDelay:0.0];

. . .

- (void)continueTheAnimation:(void*)context {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.5];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView: moviePlayerWindow cache:NO];
    [moviePlayerWindow sendSubviewToBack: overlayView];
    [moviePlayerWindow bringSubviewToFront: instructionControlsController.view];
    [UIView commitAnimations];
}
Rob
That did the trick, thanks! I'll look into performSelector a bit more - looks like they can be really handy in the future as well.
Cactuar
Turns out I spoke to soon, the bug is still there - but seems to show up even more infrequently now and it never happens in the simulator. I 'll keep investigating...
Cactuar
Since it never happens in the simulator, that makes me wonder if the device needs a little more time to get everything ready (or cleaned up). What happens if you change afterDelay: from 0.0 to 0.1 or even higher?
Rob
I don't have a better solution, but this is not a great one. You're setting up a race condition, which will behave differently in different versions of the OS and on different devices.
Kenny Winker