user3770280
user3770280

Reputation: 193

Stopping animateWithDuration before completion

I have this method in a UIViewController to show a message for three seconds and then fade it out. mainMessageLabel is a UILabel declared in the interface file.

- (void) showTempMessage: (NSString*) message
{
    _mainMessageLabel.text = message;
    _mainMessageLabel.alpha = 1;

    [UIView animateWithDuration: 1
                          delay: 3
                        options: 0
                     animations: ^{
                         _mainMessageLabel.alpha = 0;
                     }
                     completion: ^(BOOL finished) {
                         _mainMessageLabel.text = @"";
                         _mainMessageLabel.alpha = 1;
                     }];
}

The method works fine if I call it at least four seconds after the previous call, but if I call it sooner, when the previous instance is still animating, the label disappears and I have to wait another four seconds until I can call it again to work. Every time I call this method, I want it to stop the previous animation and display the new message for three seconds and fade it out.

I have tried the answers in the other questions here, such as adding UIViewAnimationOptionBeginFromCurrentState to options:, and even adding [_mainMessageLabel.layer removeAllAnimations] to the top of my function, but nothing works. Do you have any suggestions?

Upvotes: 1

Views: 523

Answers (4)

Mini
Mini

Reputation: 213

This happens because your UIview animations is getting executed in a block and since block functions are executed in a different thread you couldn't stop it in main thread.

How to fadein and fadeout in single UIView?

you could look in to this for another way of doing animation. This will help you stop and start animation at your will.

Upvotes: 0

BHASKAR
BHASKAR

Reputation: 1201

Just replace your code with this:

-(void) showTempMessage: (NSString*) message
{

    _mainMessageLabel.text = message;
    _mainMessageLabel.alpha = 1;

    [UIView animateWithDuration: 1
                          delay: 3
                        options: 0
                     animations: ^{
                         _mainMessageLabel.alpha = 0;
                     }
                     completion: ^(BOOL finished) {
                     }];
}

And from where this function is call just add following line before this.

        [_mainMessageLabel.layer removeAllAnimations];

Upvotes: 0

Rob
Rob

Reputation: 438277

The problem is the timing of the completion block (that it fires after the code that cancels the prior animation and resets the label). The easy solution is to just eliminate that completion block altogether (leaving it with alpha of zero is indistinguishable from setting the text to @"" and making it "visible"). Thus:

_mainMessageLabel.text = message;
_mainMessageLabel.alpha = 1.0;

[UIView animateWithDuration:1 delay:3 options:0 animations:^{
    _mainMessageLabel.alpha = 0.0;
} completion:nil];

Upvotes: 1

Ravi
Ravi

Reputation: 2451

try like this

- (void) showTempMessage: (NSString*) message
{
    _mainMessageLabel.text = message;
    _mainMessageLabel.alpha = 1;

   [UIView animateWithDuration: 3
                          delay: 0
                        options: 0
                     animations: ^{
                         _mainMessageLabel.alpha = 1;
                     }
                     completion: ^(BOOL finished)
                     {
                         _mainMessageLabel.text = @"";
                         _mainMessageLabel.alpha = 0;
                     }];
}

Upvotes: 0

Related Questions