【问题标题】:CADisplayLink can't stop after invalidatedCADisplayLink 失效后无法停止
【发布时间】:2016-01-03 17:54:45
【问题描述】:

我有两个UIButton,第一个按钮将触发CustomeView 的- beginAnimation,另一个按钮将触发- endAnimation。当我依次快速按下这两个按钮时,例如begin -> end -> begin -> end -> begin -> end,我发现CADisplayLink 无法停止。更何况- rotate的射速超过了60fps,变成了60 -> 120 -> 180,就像我的主RunLoop里有不止一个CADisplaylink一样,有没有办法解决呢?而且我需要在视图的 alpha 变为零之前保持CADisplaylink 运行,所以我将[self.displayLink invalidate]; 放在完成块中,也许这会导致这个问题?

@interface CustomeView : UIView
@end

@implementation CustomeView

- (void)beginAnimation // triggered by a UIButton
{
    [UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)endAnimation // triggered by another UIButton
{
    [UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
        [self.displayLink invalidate];
    }];
}

- (void)rotate
{
    // ....
}

【问题讨论】:

    标签: ios cadisplaylink


    【解决方案1】:

    如果您在-endAnimation 中的完成块运行之前调用-beginAnimation(即在0.5 秒动画完成之前),您将用新的self.displayLink 覆盖旧的self.displayLink。之后,当完成块运行时,您将使新的显示链接失效,而不是旧的。

    使用一个中间变量来捕获self.displayLink 的值,该值包含您要失效的显示链接。另外,为了更好地衡量,在完成后将 self.displayLink 设置为 nil。

    - (void)beginAnimation // triggered by a UIButton
    {
        [UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
    
        if (self.displayLink != nil) {
            // You called -beginAnimation before you called -endAnimation.
            // I'm not sure if your code is doing this or not, but if it does,
            // you need to decide how to handle it.
        } else {
            // Make a new display link.
            self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
            [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        }
    }
    
    - (void)endAnimation // triggered by another UIButton
    {
        if (self.displayLink == nil) {
            // You called -endAnimation before -beginAnimation.
            // Again, you need to determine what, if anything,
            // to do in this case.
        } else {
            CADisplayLink oldDisplayLink = self.displayLink;
            self.displayLink = nil;
    
            [UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
                [oldDisplayLink invalidate];
            }];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 2013-12-14
      相关资源
      最近更新 更多