Location>code7788 >text

iOS Development Basics 144 - Verbatim Printing Effects

Popularity:309 ℃/2024-08-01 14:38:29

In an AIGC-like app, achieving that effect of printing out text one word at a time, line by line, can be accomplished in a variety of ways. Here are some possible implementations, using Swift and OC for examples.

OC version

1. Timer-based verbatim printing effects

It is possible to useNSTimerto display the text word by word and line by line.

#import ""

@interface ViewController ()

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, assign) NSInteger currentIndex;
@property (nonatomic, strong) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

     = [[UITextView alloc] initWithFrame:];
     = [UIFont systemFontOfSize:18];
     = NO;
     = YES;
    [ addSubview:];

     = @"This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。";
     = 0;

    [self startPrinting];
}

- (void)startPrinting {
     = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(printNextCharacter) userInfo:nil repeats:YES];
}

- (void)printNextCharacter {
    if ( >= ) {
        [ invalidate];
         = nil;
        return;
    }

    NSRange range = NSMakeRange(, 1);
    NSString *nextCharacter = [ substringWithRange:range];
     = [ stringByAppendingString:nextCharacter];
    
     += 1;
}

@end

2. Using CADisplayLink to realize high-precision verbatim printing

CADisplayLinkcan be called when the screen is refreshed, as opposed to theNSTimerIt is more accurate and performs better.

#import ""

@interface ViewController ()

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, assign) NSInteger currentIndex;
@property (nonatomic, strong) CADisplayLink *displayLink;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

     = [[UITextView alloc] initWithFrame:];
     = [UIFont systemFontOfSize:18];
     = NO;
     = YES;
    [ addSubview:];
    
     = @"This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。";
     = 0;

    [self startPrinting];
}

- (void)startPrinting {
     = [CADisplayLink displayLinkWithTarget:self selector:@selector(printNextCharacter)];
     = 10; // Controlling Print Speed
    [ addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)printNextCharacter {
    if ( >= ) {
        [ invalidate];
         = nil;
        return;
    }

    NSRange range = NSMakeRange(, 1);
    NSString *nextCharacter = [ substringWithRange:range];
     = [ stringByAppendingString:nextCharacter];
    
     += 1;
}

@end

3. CATextLayer + Animation

It is also possible to useCATextLayerand animation to achieve more sophisticated and smooth word-by-word and line-by-line printing effects.

#import ""
#import <QuartzCore/>

@interface ViewController ()

@property (nonatomic, strong) CATextLayer *textLayer;
@property (nonatomic, strong) NSString *content;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

     = [CATextLayer layer];
     = ;
     = 18;
     = kCAAlignmentLeft;
     = [UIScreen mainScreen].scale;
     = YES;
    [ addSublayer:];

     = @"This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。";

    [self startPrinting];
}

- (void)startPrinting {
     = @"";
    
    for (NSInteger index = 0; index < ; index++) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(index * 0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSString *nextCharacter = [ substringWithRange:NSMakeRange(index, 1)];
             = [ stringByAppendingString:nextCharacter];
        });
    }
}

@end

Swift Edition

1. Timer-based verbatim printing effects

It is possible to useTimerto display the text word by word and line by line.

import UIKit

class ViewController: UIViewController {
    private let textView = UITextView()
    private let content = "This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。"
    private var currentIndex = 0
    private var timer: Timer?

    override func viewDidLoad() {
        ()
        (textView)
         =
         = (ofSize: 18)
         = false
         = true
        startPrinting()
    }

    private func startPrinting() {
        timer = (timeInterval: 0.1, target: self, selector: #selector(printNextCharacter), userInfo: nil, repeats: true)
    }

    @objc private func printNextCharacter() {
        guard currentIndex < else {
            timer?.invalidate()
            timer = nil
            return
        }
        
        let nextIndex = (, offsetBy: currentIndex)
        (content[nextIndex])
        currentIndex += 1
    }
}

2. Using CADisplayLink to realize high-precision verbatim printing

CADisplayLinkcan be called when the screen is refreshed, as opposed to theTimerIt is more accurate and performs better.

import UIKit

class ViewController: UIViewController {
    private let textView = UITextView()
    private let content = "This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。"
    private var currentIndex = 0
    private var displayLink: CADisplayLink?

    override func viewDidLoad() {
        ()
        (textView)
         =
         = (ofSize: 18)
         = false
         = true
        startPrinting()
    }

    private func startPrinting() {
        displayLink = CADisplayLink(target: self, selector: #selector(printNextCharacter))
        displayLink?.preferredFramesPerSecond = 10 // Controlling Print Speed
        displayLink?.add(to: .main, forMode: .default)
    }

    @objc private func printNextCharacter() {
        guard currentIndex < else {
            displayLink?.invalidate()
            displayLink = nil
            return
        }
        
        let nextIndex = (, offsetBy: currentIndex)
        (content[nextIndex])
        currentIndex += 1
    }
}

3. CATextLayer + Animation

It is also possible to useCATextLayerand animation to achieve more sophisticated and smooth word-by-word and line-by-line printing effects.

import UIKit

class ViewController: UIViewController {
    private let textLayer = CATextLayer()
    private let content = "This is the text content that needs to be printed word by word and line by line。\nLet's make it happen.。"
    
    override func viewDidLoad() {
        ()
        
         =
         = 18
         = .left
         =
         = true
        (textLayer)
        
        startPrinting()
    }
    
    private func startPrinting() {
         = ""
        for (index, character) in () {
            (deadline: .now() + Double(index) * 0.1) {
                 = "\( ?? "")\(character)"
            }
        }
    }
}