0

I have following scenario :

dispatch_after_delta(0.1, ^{
    [self checkForTodaysBonus];  // It contains animation methods.
});

And

-(void) checkForTodaysBonus {
     // Prepare View and other data and then animate UIView
     [Animations moveDown:self.view andAnimationDuration:0.3 andWait:YES andLength:self.view.frame.size.height];
}

where, moveDown method is like :

+ (void) moveDown: (UIView *)view andAnimationDuration: (float) duration andWait:(BOOL) wait andLength:(float) length{
    __block BOOL done = wait; //wait =  YES wait to finish animation
    [UIView animateWithDuration:duration animations:^{
        view.center = CGPointMake(view.center.x, view.center.y + length);

    } completion:^(BOOL finished) {
         // This never happens if I call this method from dispatch_after. 
         done = NO;
    }];
    // wait for animation to finish
    // This loop will allow wait to complete animation
      while (done == YES) {  // Application unable to break this condition
         [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
       }
}

And

 void dispatch_after_delta(float delta, dispatch_block_t block){
       dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta * NSEC_PER_SEC), dispatch_get_main_queue(), block);
 }

So, issue, whenever animation method is called from dispatch_after_delta, animation method never gets its completion block.

What could be possible solution ?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Devang
  • 11,258
  • 13
  • 62
  • 100
  • Maybe this can help: http://stackoverflow.com/questions/4139219/how-do-you-trigger-a-block-after-a-delay-like-performselectorwithobjectafter – Sergei Nikitin Apr 29 '14 at 13:21
  • @SergeyNikitin : Please check, thats what I am doing. I am using dispatch_after_delay. Main issue is UIViewAnimation is not getting completion method. – Devang Apr 29 '14 at 13:28

2 Answers2

0

My advice to you would be to use performSelector: withObject: afterDelay:.

Replace your current dispatch_after with:

[self performSelector:@selector(checkForTodaysBonus) withObject:nil afterDelay:1.0f];
Infinity James
  • 4,667
  • 5
  • 23
  • 36
  • Yes, thats good thing, but at some places, I have to create different method to use performSelector..so I am looking for solution with dispatch_after – Devang Apr 29 '14 at 17:04
0

Than's because you submit the block

^{
   [self checkForTodaysBonus];  // It contains animation methods.
});  

to the main queue,and main queue is a serial queue,so the animation completion block won't execute until the block above return.

To solve this issue,you can :

  1. submit the block to the global queue
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
  2. execute the animation in the main queue :

    dispatch_async(dispatch_get_main_queue(), ^{
    [UIView animateWithDuration:duration animations:^{
        view.center = CGPointMake(view.center.x, view.center.y + length);
    
    } completion:^(BOOL finished) {
        // This never happens if I call this method from dispatch_after.
        done = NO;
    }];
    

    });

In my opinion,you'd better not to use NSThread and NSRunLoop explicitly in the dispatch block.

NSOiO
  • 249
  • 2
  • 4