iOS使用CoreText完成txt阅读器

news/2024/7/20 20:26:16 标签: ios, cocoa, macos

介绍几个关键方法

由属性字符串得到CTFramesetter

  • CTFramesetterCreateWithAttributedString(att as CFAttributedString)

CTFramesetter是NSAttributedString的CF对象,可以直接强转;
 

生成CTFrame

  • CTFramesetterCreateFrame(framesetter, CFRangeMake(pageStart, 0), path, nil)

CTFrame是排版数据,由CTFramesetter生成;
 

计算分页

  • CTFrameGetVisibleStringRange(frame)
     

通过上面的介绍,把这几个函数连起来,就是数据准备阶段的核心方法:

  1. 根据txt内容生成framesetter,
  2. 根据页面大小计算生成单页的CTFrame
  3. 循环计算分页,保存得到每页的内容范围和每页的CTFrame
func createCTFrame(contentStr: String) {

    let range = NSMakeRange(0, contentStr.count)
    let att = NSMutableAttributedString(string: contentStr)

    att.addAttribute(.foregroundColor, value: UIColor.lightGray, range: range)

    att.addAttribute(.font, value: UIFont.systemFont(ofSize: 22), range: range)

    let framesetter = CTFramesetterCreateWithAttributedString(att as CFAttributedString)
    let path = CGPath(rect: self.readView.bounds, transform: nil)

    var pageStart = 0
    var frameArray: [CTFrame] = []

    var i: Int = 0

    repeat {

        let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(pageStart, 0), path, nil)

        let pageRange = CTFrameGetVisibleStringRange(frame)

        let beginIndex = contentStr.index(contentStr.startIndex, offsetBy: pageRange.location)
        let endIndex = contentStr.index(beginIndex, offsetBy: pageRange.length)
        let onePage = String(contentStr[beginIndex..<endIndex])
        pageStart = pageRange.location + pageRange.length


        print("第\(i)页" ,pageRange, onePage)

        i+=1
        frameArray.append(frame)
    } while(pageStart < contentStr.count )
    self.frameArray = frameArray

}

渲染的核心方法,在继承UIView的子类中,重写drawrect方法,里面最重要的一行就是CTFrameDraw(frame, ctx),即可完成渲染:

/// 绘制
override func draw(_ rect: CGRect) {
    guard let frame = frameRef, let ctx = UIGraphicsGetCurrentContext() else {
        return
    }
    ctx.textMatrix = CGAffineTransform.identity
    ctx.translateBy(x: 0, y: bounds.size.height)
    ctx.scaleBy(x: 1.0, y: -1.0)
    CTFrameDraw(frame, ctx)
}

比较完整的txt阅读器demo:

iOS: .txt 小说阅读器功能开发的 5 个老套路 - 掘金

套路继续, .txt 小说阅读器功能开发 - 掘金
 

最简版demo: 使用coretext计算分页并渲染,上面demo的功能多,导致核心逻辑淹没在业务代码中,找起来麻烦,所以做了一个只展示核心原理的最简demo : 使用coretext渲染,解析txt文件功能

 博客园系列文章:

https://www.cnblogs.com/summer-blog/p/6030641.html

https://www.cnblogs.com/summer-blog/p/6030885.html

https://www.cnblogs.com/summer-blog/p/6044118.html

https://www.cnblogs.com/summer-blog/p/6402664.html

比较精细的阅读器思路,页面行高重排,目前我们还用不到

我在七猫做阅读器——排版篇

从基础的各种CoreText渲染,到页面之间切换动画都有独立的demo,最后有一个把CoreText渲染+页面切换集成在一起的demo

小说阅读器的设计和实现 - 简书

GitHub - loyinglin/LearnCoreText


http://www.niftyadmin.cn/n/5252310.html

相关文章

Web漏洞扫描工具有哪些?使用教程讲解

作为网络安全工程师&#xff0c;了解并掌握各种Web漏洞扫描工具对于识别和防御网络威胁至关重要。以下是一些常用且广受推崇的Web漏洞扫描工具&#xff0c;它们覆盖了从自动扫描到深度定制的各种需求。希望你能用得到呢。 1. OWASP ZAP (Zed Attack Proxy) 原理&#xff1a;…

Java毕业设计—vue+SpringBoot图书借阅管理系统

图书管理系统 1. 开发目的 实现图书的智能化、信息化和简单化&#xff1b;实现图书信息的增加、删除、修改、查找、借阅、还书、收藏的显示操作及实时数据库的提交和更改和对普通用户的增、删、改、查&#xff1b;提高图书管理员工作信息报送及反馈的工作效率&#xff0c;减轻…

Java 简易版 TCP UDP聊天

客户端 import java.io.*; import java.net.Socket; import java.util.Date; import javax.swing.*;public class MyClient {private JFrame jf;private JButton jBsend;private JTextArea jTAcontent;private JTextField jText;private JLabel JLcontent;private Date data;pr…

嵌入式培训-Linux系统及C编程高级-DAY6-linux shell脚本编程

Shell脚本概述 Shell脚本是利用 shell 的功能所写的一个程序。这个程序是使用纯文本文件&#xff0c;将一些 shell 的语法与命令&#xff08;含外部命令&#xff09;写在里面&#xff0c;搭配正则表达式、管道命令与数据流重定向等功能 Shell脚本编写流程 Shell脚本的文件扩展名…

玩转大数据12:大数据安全与隐私保护策略

1. 引言 大数据的快速发展&#xff0c;为各行各业带来了巨大的变革&#xff0c;也带来了新的安全和隐私挑战。大数据系统通常处理大量敏感数据&#xff0c;包括个人身份信息、财务信息、健康信息等。如果这些数据被泄露或滥用&#xff0c;可能会对个人、企业和社会造成严重的损…

【网络奇缘】- 计算机网络|深入学习物理层|网络安全

​ &#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 回顾链接&#xff1a;http://t.csdnimg.cn/ZvPOS 这篇文章是关于深入学习原理参考模型-物理层的相关知识点&…

2023济南大学acm新生赛题解

通过答题情况的难度系数&#xff1a; 签到&#xff1a;ACI 铜牌题&#xff1a;BG 银牌题&#xff1a;EF 金牌题&#xff1a;DHJKO 赛中暂未有人通过&#xff1a;LMNP A - AB Problem 直接根据公式计算就行。 #include<stdio.h> int main(){int a,b;scanf("%…

C语言进阶之路-数据结构篇

目录 一、学习目标 二、数据结构 1.基本概念 线性关系&#xff1a; 非线性关系&#xff1a; 存储形式 2. 算法分析 2.1 时间复杂度 2.2 空间复杂度 2.3 时空复杂度互换 总结 一、学习目标 了解数据结构的基本概念了解算法的分析方法 二、数据结构 1.基本概念 数据结…