1

I want to animate the text of a UILabel so that it shows one text for a couple of seconds and after that fades into a default text.

I'm currently using the following code:

-(void)tapOnBalance:(id)sender{
      [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        cell.amountLabel.text = @"Hola!";
      } completion:nil];

      // Pause the function - act as a 'delay'
      [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

      [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        cell.amountLabel.text = @"Hallo!";
      } completion:nil];

}

This works, but the [NSRunLoop currentRunLoop] is pausing the entire app, blocking everything for 3 seconds.

How do I get rid of the block on the main thread and still get the same result?

jscs
  • 63,694
  • 13
  • 151
  • 195
bdv
  • 1,154
  • 2
  • 19
  • 42
  • 1
    Have you considered using the "delay" parameter of the animation methods? – jscs Nov 02 '14 at 19:41
  • Yes, but they don't work on `UILabels` – bdv Nov 02 '14 at 19:42
  • 1
    Don't know about the downvote, but (1) you don't have to pause the main thread in this case... utilize the completion block and delay instead. (2) Check out this answer for help on how to do this sort of UILabel transition properly: http://stackoverflow.com/a/16367409/2274694 – Lyndsey Scott Nov 02 '14 at 19:54
  • 1
    possible duplicate of [setting new text to uilabel and animation](http://stackoverflow.com/questions/3073520/setting-new-text-to-uilabel-and-animation) – memmons Nov 02 '14 at 20:46

1 Answers1

1

A simple fade (not a cross-fade) can go like this:

// change a label's text after some delay by fading
// out, changing the text, then fading back in
- (void)fadeLabel:(UILabel *)label toText:(NSString *)toText completion:(void (^)(BOOL))completion {
    [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        label.alpha = 0.0;
    } completion:^(BOOL finished) {
        label.text = toText;
        [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            label.alpha = 1.0;
        } completion:completion];
    }];
}

// simpler signature that can be done on a perform
- (void)changeLabelText:(NSString *)toText {
    [self fadeLabel:self.myLabel toText:toText completion:nil];
}

// set the label to something, then change it with a fade, then change it back
self.myLabel.text = @"text";
[self performSelector:@selector(changeLabelText:) withObject:@"hola!" afterDelay:4];
[self performSelector:@selector(changeLabelText:) withObject:@"text" afterDelay:8];

You could also nest the calls' completion blocks (and add a delay param) to do something similar without the performs. To do a cross-fade, apply a similar technique with two labels (that have the same frame) where one's alpha is zero and the other's alpha is one.

danh
  • 62,181
  • 10
  • 95
  • 136
  • This causes the entire `UILabel` to fade, and a crossfade animation only animates the text, which is what I want. – bdv Nov 02 '14 at 21:38
  • Are you saying you need me to explain how to do a cross-fade? – danh Nov 03 '14 at 03:41