来自dispatch_after的UIViewAnimation阻止UIViewAnimation完成块

时间:2014-04-29 11:55:12

标签: ios objective-c grand-central-dispatch uiviewanimation

我有以下情况:

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

并且

-(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];
}

其中,moveDown方法如下:

+ (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]];
       }
}

 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);
 }

所以,问题,只要从animationdispatch_after_delta方法animation调用never gets its completion block方法。

什么是可能的解决方案?

2 个答案:

答案 0 :(得分:0)

我给你的建议是使用performSelector: withObject: afterDelay:

将当前的dispatch_after替换为:

[self performSelector:@selector(checkForTodaysBonus) withObject:nil afterDelay:1.0f];

答案 1 :(得分:0)

比因为你提交了块

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

到主队列,主队列是一个串行队列,因此动画完成块不会执行,直到上面的块返回。

要解决此问题,您可以:

  1. 将块提交到全局队列
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
  2. 在主队列中执行动画:

    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;
    }];
    

    });

  3. 在我看来,您最好不要在调度块中明确使用NSThread和NSRunLoop。