Cancel block in UIView animateWithDuration

笑着哭i 提交于 2020-01-02 05:40:15

问题


- (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?
}

In my UIView's initWithFrame, I build some loader graphics then start the loader animation from [self startLoading].

The question is now, how do I stop this 'infinite loop'? or what goes in the stopLoading or dealloc method to nicely tear everything down?

When I ignore the fact that a completion block is there and just release my UIView from the super view, everything goes fine for some seconds (more than the 0.5 sec specified) then the app crashes with a message:

malloc: * mmap(size=2097152) failed (error code=12) error: can't allocate region ** set a breakpoint in malloc_error_break to debug

I have a breakpoint in malloc_error_break and the culprit is the animation block.

I assume that the UIView was released by being removed from the super view and later on the completion block is executed, having a reference to self this is messaging a released object.

I can't find anything in the docs about canceling a 'queued' block.


回答1:


To cancel, do what you would do with any looping operation you want to be able to cancel: set a flag which you check each time before looping. So:

- (void) stopLoading {
    kCancel = YES;
}

And now your completion block looks like this:

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

kCancel could be an ivar, a static global variable, whatever.




回答2:


UIViewAnimationOptionRepeat has magic for u

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



回答3:


I just repeat the animation and kill it after some time with a dispatch block:

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


来源:https://stackoverflow.com/questions/6766034/cancel-block-in-uiview-animatewithduration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!