首页 > 其他分享 >iOS开发基础144-逐字打印效果

iOS开发基础144-逐字打印效果

时间:2024-08-01 14:41:02浏览次数:13  
标签:144 逐字 self iOS content textLayer currentIndex textView

在AIGC类的APP中,实现那种一个字一个字、一行一行地打印出文字的效果,可以通过多种方法来实现。下面是一些实现方法,使用Swift和OC来举例说明。

OC版

1. 基于定时器的逐字打印效果

可以使用NSTimer来逐字逐行地显示文字。

#import "ViewController.h"

@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];

    self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
    self.textView.font = [UIFont systemFontOfSize:18];
    self.textView.editable = NO;
    self.textView.scrollEnabled = YES;
    [self.view addSubview:self.textView];

    self.content = @"这是需要逐字逐行打印的文字内容。\n让我们来实现它。";
    self.currentIndex = 0;

    [self startPrinting];
}

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

- (void)printNextCharacter {
    if (self.currentIndex >= self.content.length) {
        [self.timer invalidate];
        self.timer = nil;
        return;
    }

    NSRange range = NSMakeRange(self.currentIndex, 1);
    NSString *nextCharacter = [self.content substringWithRange:range];
    self.textView.text = [self.textView.text stringByAppendingString:nextCharacter];
    
    self.currentIndex += 1;
}

@end

2. 使用CADisplayLink来实现高精度逐字打印

CADisplayLink可以在屏幕刷新时调用指定的方法,相较于NSTimer,其精度和性能更高。

#import "ViewController.h"

@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];

    self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
    self.textView.font = [UIFont systemFontOfSize:18];
    self.textView.editable = NO;
    self.textView.scrollEnabled = YES;
    [self.view addSubview:self.textView];
    
    self.content = @"这是需要逐字逐行打印的文字内容。\n让我们来实现它。";
    self.currentIndex = 0;

    [self startPrinting];
}

- (void)startPrinting {
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(printNextCharacter)];
    self.displayLink.preferredFramesPerSecond = 10; // 控制打印速度
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)printNextCharacter {
    if (self.currentIndex >= self.content.length) {
        [self.displayLink invalidate];
        self.displayLink = nil;
        return;
    }

    NSRange range = NSMakeRange(self.currentIndex, 1);
    NSString *nextCharacter = [self.content substringWithRange:range];
    self.textView.text = [self.textView.text stringByAppendingString:nextCharacter];
    
    self.currentIndex += 1;
}

@end

3. CATextLayer + Animation

还可以使用CATextLayer和动画来实现更为复杂和流畅的逐字逐行打印效果。

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

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

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.textLayer = [CATextLayer layer];
    self.textLayer.frame = self.view.bounds;
    self.textLayer.fontSize = 18;
    self.textLayer.alignmentMode = kCAAlignmentLeft;
    self.textLayer.contentsScale = [UIScreen mainScreen].scale;
    self.textLayer.wrapped = YES;
    [self.view.layer addSublayer:self.textLayer];

    self.content = @"这是需要逐字逐行打印的文字内容。\n让我们来实现它。";

    [self startPrinting];
}

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

@end

Swift版

1. 基于定时器的逐字打印效果

可以使用Timer来逐字逐行地显示文字。

import UIKit

class ViewController: UIViewController {
    private let textView = UITextView()
    private let content = "这是需要逐字逐行打印的文字内容。\n让我们来实现它。"
    private var currentIndex = 0
    private var timer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(textView)
        textView.frame = view.bounds
        textView.font = UIFont.systemFont(ofSize: 18)
        textView.isEditable = false
        textView.isScrollEnabled = true
        startPrinting()
    }

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

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

2. 使用CADisplayLink来实现高精度逐字打印

CADisplayLink可以在屏幕刷新时调用指定的方法,相较于Timer,其精度和性能更高。

import UIKit

class ViewController: UIViewController {
    private let textView = UITextView()
    private let content = "这是需要逐字逐行打印的文字内容。\n让我们来实现它。"
    private var currentIndex = 0
    private var displayLink: CADisplayLink?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(textView)
        textView.frame = view.bounds
        textView.font = UIFont.systemFont(ofSize: 18)
        textView.isEditable = false
        textView.isScrollEnabled = true
        startPrinting()
    }

    private func startPrinting() {
        displayLink = CADisplayLink(target: self, selector: #selector(printNextCharacter))
        displayLink?.preferredFramesPerSecond = 10  // 控制打印速度
        displayLink?.add(to: .main, forMode: .default)
    }

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

3. CATextLayer + Animation

还可以使用CATextLayer和动画来实现更为复杂和流畅的逐字逐行打印效果。

import UIKit

class ViewController: UIViewController {
    private let textLayer = CATextLayer()
    private let content = "这是需要逐字逐行打印的文字内容。\n让我们来实现它。"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textLayer.frame = view.bounds
        textLayer.fontSize = 18
        textLayer.alignmentMode = .left
        textLayer.contentsScale = UIScreen.main.scale
        textLayer.isWrapped = true
        view.layer.addSublayer(textLayer)
        
        startPrinting()
    }
    
    private func startPrinting() {
        textLayer.string = ""
        for (index, character) in content.enumerated() {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.1) {
                self.textLayer.string = "\(self.textLayer.string ?? "")\(character)"
            }
        }
    }
}

标签:144,逐字,self,iOS,content,textLayer,currentIndex,textView
From: https://www.cnblogs.com/chglog/p/18336612

相关文章

  • 大厂面经: 字节跳动 iOS开发实习生-飞书
    好家伙,线上面试,总时长1h30mins左右整体流程:0.自我介绍(0-2mins)1.做的比较难的事情(15min)我讲我之前写的一个低开平台,写了一个撤销回退功能,提了个pr,用了节流,用了命令模式1.1.节流怎么用的?用在哪?为什么用?1.2.节流把前面的触发直接clean了还是怎么处理?会不会清除掉一......
  • ios CCUIView.m
    ////CCUIView.h//CCFC////#import<Foundation/Foundation.h>#import"CCUIButton.h"//创建UI控件的宏#defineUI_ALLOC_CREATE(UIctlName,x,y,width,height)[[UIctlNamealloc]initWithFrame:CGRectMake((x),(y),(width),(height))]#defi......
  • ios CCNSURL.m
    ////CCNSURL.h//CCFC////#import<Foundation/Foundation.h>@interfaceNSURL(cc)+(NSString*)telephonePrefix;+(NSString*)smsPrefix;+(NSString*)mailPrefix;+(NSString*)googleMapPrefix;@end////CCNSURL.m//CCFC////......
  • ios CCUIToolBar.m
    ////CCUIToolbar.h//CCFC////#import<Foundation/Foundation.h>#import<UIKit/UIToolbar.h>@interfaceUIToolbar(cc)//createacommontoolbar+(UIToolbar*)createCommonToolbar:(CGRect)rectitems:(NSArray*)buttonItemArr;@end /......
  • 建议所有iPhone升级!苹果iOS 17.6正式版发布:重要错误修复
    苹果发布iOS17.6正式版升级,本次更新距离iOS17.5发布已有两个月时间。升级日志显示,iOS17.6提供重要的错误修复和安全性更新,苹果建议所有用户安装。不出意外的话,iOS17.6将是iOS17最后几次更新之一,后续将仅提供必须的安全更新和Bug修复,苹果的开发重心会转移到iOS18上。根据......
  • vue基础知识总结(2)--- axios的使用
    一.下载Vue3:选择自己想要下载的项目文件夹,cmd回车打开命令栏,执行:cnpminitvue@latest然后等待一会就可以创建一个项目,并更改项目名:√请输入项目名称:...vue-project之后按照提示输入对应的语句:cdvue-projectcnpminstall我们等待几秒Vue3项目就成功创建出来了......
  • 如何让 flet 在 iOS 上打开照片而不是文件?
    我正在尝试使用Flet构建一个Python移动应用程序,我需要它做的事情之一就是接受用户的照片或视频。使用flet文档,我尝试了以下代码:ft.ElevatedButton("Choosefiles...",on_click=lambda_:file_picker.pick_files(allow_multiple=True))在iOS上打开文件选择器......
  • 瑞士ABB苏黎世张力控制器系统PFEA113-65订货号3BSE028144R65
    光学编码器光学编码器信号链元件与磁编码器(AMR)部分介绍的元件几乎相同。但是,为了支持高的编码器分辨率,建议使用AD77602.5MSPS、24位、100dBΣ-ΔADC。它融合了宽输入带宽、高速特性和Σ-Δ转换技术的优势,2.5MSPS时信噪比(SNR)可达100dB,因此非常适合高速数据采集应用。旋变(耦......
  • 【iOS】——KVC和KVO
    KVCKVC定义KVC(Key-valuecoding)键值编码,允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性。而不是在编译时确定。也就是说它提供一种机制来间接访问对象的属性,而不是通过调用Sett......
  • BUG 太多?苹果罕见“重新推送”ios18 beta 4测试版
    在刚刚过去的周末,苹果公司面向开发者,重新发布了iOS/ iPadOS18Beta4更新,内部版本号从22A5316j 变为 22A5316k,目前尚不清楚两个Beta4版本更新之间的区别。此次更新包大小仅为251M左右,是更新。对于已经注册的开发者可以打开“设置”应用程序,进入“软件更新”部......