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 useNSTimer
to 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
CADisplayLink
can be called when the screen is refreshed, as opposed to theNSTimer
It 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 useCATextLayer
and 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 useTimer
to 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
CADisplayLink
can be called when the screen is refreshed, as opposed to theTimer
It 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 useCATextLayer
and 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)"
}
}
}
}