问题
- (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