Letter by letter animation for UILabel?

Is there a way to animate the text displayed by UILabel. I want it to show the text value character by character.

Help me with this folks


Update for 2018, Swift 4.1:

extension UILabel {

    func animate(newText: String, characterDelay: TimeInterval) {

        DispatchQueue.main.async {

            self.text = ""

            for (index, character) in newText.enumerated() {
                DispatchQueue.main.asyncAfter(deadline: .now() + characterDelay * Double(index)) {
                    self.text?.append(character)
                }
            }
        }
    }

}

calling it is simple and thread safe:

myLabel.animate(newText: myLabel.text ?? "May the source be with you", characterDelay: 0.3)

@objC, 2012:

Try this prototype function:

- (void)animateLabelShowText:(NSString*)newText characterDelay:(NSTimeInterval)delay
{    
    [self.myLabel setText:@""];

    for (int i=0; i<newText.length; i++)
    {
        dispatch_async(dispatch_get_main_queue(),
        ^{
            [self.myLabel setText:[NSString stringWithFormat:@"%@%C", self.myLabel.text, [newText characterAtIndex:i]]];
        });

        [NSThread sleepForTimeInterval:delay];
    }
}

and call it in this fashion:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
    [self animateLabelShowText:@"Hello Vignesh Kumar!" characterDelay:0.5];
});

Here's @Andrei G.'s answer as a Swift extension:

extension UILabel {

    func setTextWithTypeAnimation(typedText: String, characterInterval: NSTimeInterval = 0.25) {
        text = ""
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
            for character in typedText.characters {
                dispatch_async(dispatch_get_main_queue()) {
                    self.text = self.text! + String(character)
                }
                NSThread.sleepForTimeInterval(characterInterval)
            }
        }
    }

}

This might be better.

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *string =@"Risa Kasumi & Yuma Asami";

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:string forKey:@"string"];
    [dict setObject:@0 forKey:@"currentCount"];
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(typingLabel:) userInfo:dict repeats:YES];
    [timer fire];


}

-(void)typingLabel:(NSTimer*)theTimer
{
    NSString *theString = [theTimer.userInfo objectForKey:@"string"];
    int currentCount = [[theTimer.userInfo objectForKey:@"currentCount"] intValue];
    currentCount ++;
    NSLog(@"%@", [theString substringToIndex:currentCount]);

    [theTimer.userInfo setObject:[NSNumber numberWithInt:currentCount] forKey:@"currentCount"];

     if (currentCount > theString.length-1) {
        [theTimer invalidate];
    }

    [self.label setText:[theString substringToIndex:currentCount]];
}

I have write a demo , you can use it , it support ios 3.2 and above

in your .m file

- (void)displayLabelText
{

    i--;
    if(i<0)
    {
        [timer invalidate];
    }
    else
    {
        [label setText:[NSString stringWithFormat:@"%@",[text substringToIndex:(text.length-i-1)]]];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 60)];
    [label setBackgroundColor:[UIColor redColor]];
    text = @"12345678";
    [label setText:text];
    [self.view addSubview:label];
    i=label.text.length;
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(displayLabelText) userInfo:nil repeats:YES];
    [timer fire];    
}

in your .h file

@interface labeltextTestViewController : UIViewController {
    UILabel *label;
    NSTimer *timer;
    NSInteger i;
    NSString *text;
}

with the demo , i think you can do in your situation , with a little change the code look like very very ugly because i have to go to have dinner, you can majorization it.