Quick series of [UIView transitionWithView...] not going smoothly

963 views Asked by At

I've got a view which is a 4x4 grid of images, and am trying to achieve the effect of every square, going from top to bottom and left to right, flipping over to reveal a new image. Should be a bit of a "ripple" effect, so the top left square starts flipping immediately, the [0,1] square flips after 0.05 seconds, [0,2] after 0.10 seconds, and so on, so that after (0.05*15) seconds the final square starts to flip.

My implementation is this: Each grid square is a UIView subclass, DMGridSquareView, which contains a UIImageView, and the following method:

- (void)flipToNewImage:(UIImage*)img {
    AATileView *mySelf = self;

    [UIView transitionWithView:self.imageView
                      duration:0.4
                       options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
                                  self.imageView.image = img;
                               } completion:^(BOOL finished) {
                                  NSLog(@"Finished flip");
                               }];
}

Then, in order to trigger the animation of all the grid squares, within the DMGridView, I call this method:

- (void)flipAllSquares:(NSArray*)newImages {
    int numTiles = self.numColumns * self.numRows;
    for (int idx=0; idx<numTiles; idx++) {
        UIImage *newImg = [newImages objectAtIndex:idx];
        [[self.gridSquareViews objectAtIndex:idx] performSelector:@selector(flipToNewImage:) withObject:newImg afterDelay:(0.05*idx)];
    }
}

When running on the simulator, this works beautifully. But when running on my iPhone 5, it has an unexpected (to me, at least) behavior. The animations of the individual grid squares are nice and smooth, and at the correct speed, but the start times are off. They happen in staggered "chunks". So the first 2 squares might flip immediately, then the next 4 squares will simultaneously flip after a moment, then the next 3 flip after another moment, and so on. It's not consistent, but it's always in chunks like this.

Any idea how to fix this?

Thanks.

1

There are 1 answers

4
Chris On

EDIT 1:

Sorry, it looks like I misunderstood your question. You do not want them to flip one after another, you would like each view to begin flipping very soon after the previous view has begun flipping.

Have you tried calling the method recursively from the completion block? This way you know the method is only being called after the previous image has completed the flip animation.

NSInteger imageFlipIndex = 0;

- (void)flipToNewImage:(UIImage*)img {
    AATileView *mySelf = self;

    [UIView transitionWithView:self.imageView
                      duration:0.4
                       options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
                                  self.imageView.image = img;
                               } completion:^(BOOL finished) {
                                  imageFlipIndex++;
                                  if (imageFlipIndex < newImages.count) {
                                      UIImage *newImg = [newImages objectAtIndex:idx];
                                      [self flipToNewImage:newImg];
                                  } else {
                                      imageFlipIndex = 0;    
                                  }
                                  NSLog(@"Finished flip");
                               }];
}

What happens if you try:

imageFlipIndex++;
if (imageFlipIndex < newImages.count) {
    UIImage *newImg = [newImages objectAtIndex:idx];
    [[self.gridSquareViews objectAtIndex:imageFlipIndex] performSelector:@selector(flipToNewImage:) withObject:newImg afterDelay:(0.05*idx)];
} else {
    imageFlipIndex = 0;    
}

inside the animations block?