【问题标题】:Cancel block in UIView animateWithDurationUIView animateWithDuration 中的取消块
【发布时间】:2011-07-20 17:36:14
【问题描述】:
- (void) startLoading {

    [self blink];
} 

 - (void) blink {  

        [UIView animateWithDuration:0.5
                              delay: 0.0
                            options: UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseOut
                         animations:^{
                            //animate stuff
                         }
                         completion:^(BOOL finished){
                                 [self blink];    
                         }];

}

- (void) stopLoading {
    //What goes here?
}

在我的 UIView 的initWithFrame 中,我构建了一些加载器图形,然后从[self startLoading] 启动加载器动画。

现在的问题是,我该如何停止这个“无限循环”? 或者 stopLoading 或 dealloc 方法中的哪些内容可以很好地破坏所有内容?

当我忽略存在完成块的事实并从超级视图中释放我的 UIView 时,一切正常几秒钟(超过指定的 0.5 秒)然后应用程序崩溃并显示一条消息:

malloc: * mmap(size=2097152) 失败(错误代码=12) 错误:无法分配区域 ** 在 malloc_error_break 中设置断点进行调试

我在 malloc_error_break 中有一个断点,罪魁祸首是动画块。

我假设 UIView 是通过从超级视图中删除并稍后执行完成块来释放的,引用 self 这是消息释放的对象。

我在文档中找不到有关取消“排队”块的任何内容。

【问题讨论】:

    标签: cocoa-touch objective-c-blocks


    【解决方案1】:

    要取消,请执行您希望能够取消的任何循环操作:设置一个标志,每次循环前检查该标志。所以:

    - (void) stopLoading {
        kCancel = YES;
    }
    

    现在你的完成块看起来像这样:

    completion:^(BOOL finished){
        if (!kCancel)
            [self blink];    
    }];
    

    kCancel 可以是 ivar、静态全局变量等等。

    【讨论】:

    • 再次感谢马特。我正在慢慢了解动画块的问题 - 特别是它不是“免费”内存/CPU。
    • 这种方法有一个不便之处。如果在飞行中动画块完成之前将 NO 分配给标志 kCancel,则再次调用 blink 方法。小心它。我希望有一种方法可以像 cancelPreviousPerformRequestsWithTarget 一样永久取消块,但显然没有办法。
    • 次要点,但kVariable 命名约定实际上应该只用于真正的静态值 - 例如,您的类中按钮的标准宽度等。这些实际上通常用const 参数。 -- 相反,只需使用描述性变量名。
    • 不知道kCancel这个变量名从何而来;这不是我通常说的那种事情。无论如何,我在这里提出的解决方案不是我通常会使用的解决方案;原始问题中代码的奇怪结构迫使我这样做。通常我会直接设置一个重复无限动画的属性;这会杀死动画。
    【解决方案2】:

    UIViewAnimationOptionRepeat 对你有魔力

    [UIView animateWithDuration:0.5
                          delay: 0.0
                        options: UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionRepeat
                     animations:^{
                             //animate stuff
                     }
                     completion:^(BOOL finished){
                         NSLog(@"solved ");    
                     }];
    

    【讨论】:

    • 谢谢:) 但是,在眨眼方法中的动画块之外,我增加了一个变量。如果我使用重复选项,动画块只会被调用一次(然后在其他地方重复)并且永远不会调用完成块。据我所知,我需要使用“递归”方法。除非我当然错了:)
    【解决方案3】:

    我只是重复动画并在一段时间后使用调度块将其杀死:

    - (void)animate // Blink a view three times
    {
        // We need to stop the animation after a while (0.9 sec)
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.9 * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        {
            [view.layer removeAllAnimations];
            view.alpha = 0.0; // Animation clean-up
        });
    
        [UIView animateWithDuration:0.15 // 0.15*6=0.9: It will animate six times (three in reverse)
                              delay:0.0
                            options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
                         animations:^{
                             view.alpha = 1.0; // Animation
                         }
                         completion:NULL];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      相关资源
      最近更新 更多