1
votes

I had a UIView block-based animation that looks like this:

 [UIView animateWithDuration:0.5
                          //sequential delays
                          delay:3.0 * (float)(index/25)
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         // set myself as delegate
                         [UIView setAnimationDelegate:self];
                         // when animation stared, play some sound
                         [UIView setAnimationWillStartSelector:@selector(playDrawCardSound)];
                         // some animation results here
                     }
                     completion:^(BOOL finished){
                         // this log will never be printed out.
                         NSLog(@"finished");
                     }];

So, the problem is that all animations are fine, but the completion handler never got called.

Also, the reason that I am using delegate is because animations block will not be delayed as animations. That being said, all the sounds are played at once (not like animations which have delays between them).

Anybody know how to let code in animations block actually get delayed? Thanks!

2
Don't set the delegate or the start selector. The old animation API shouldn't really be used anymore and you definitely can't combine them. Put the animation model updates in the animations block.Jason Coco

2 Answers

0
votes

You shouldn't use setAnimationDelegate or setAnimationWillStartSelector because document says Use of this method is discouraged in iOS 4.0 and later. If you are using the block-based animation methods, you can include your delegate’s start code directly inside your block.

Also setAnimationDelegate and setAnimationWillStartSelector must be called between calls to the beginAnimations:context: and commitAnimations methods which are discouraged in iOS 4.0 and later.

It may not precise but I think it may help.

NSTimeInterval delay = 3.0 * (float)(index/25) ;
    [UIView animateWithDuration:0.5
     //sequential delays
                          delay:delay
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         [self performSelector:@selector(playDrawCardSound) withObject:nil afterDelay:delay] ;
                         // some animation results here
                     }
                     completion:^(BOOL finished){
                         // this log will never be printed out.
                         NSLog(@"finished");
                     }];
0
votes

I think you should not call delay methods in UIViewAnimation, you can just try this:

NSTimeInterval delayInterval = 3.0 * (float)(index/25);
[self performSelector:@selector(playDrawCardSound) withObject:nil afterDelay:delayInterval];
[UIView animateWithDuration:0.5
                          //sequential delays
                          delay:delayInterval
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         // some animation results, 
                         //to do logic things in finish block or delay method above will be better
                     }
                     completion:^(BOOL finished){
                         // this log will never be printed out.
                         NSLog(@"finished");
                     }];

Try performSelector with param:

[self performSelector:@selector(doDelayTast:) withObject:[NSDate date] afterDelay:4];

- (void)doDelayTast:(id)obj{
    NSDate *preDate = obj;
    NSLog(@"Delay timeinterval:%f", [[NSDate date] timeIntervalSinceDate:preDate]);
}

The result:

Delay timeinterval:4.066990

Note that, 4s is the minimum time before the message is sent, but this can be ignored in most time.