StyledTextKit
是一个用于快速渲染和简单字符串构建的声明式属性字符串库。它作为 NSAttributedString
和 UILabel
的简单替代方案,用于后台线程大小和位图缓存。
功能
- 声明式属性字符串构建 API
- 在不产生清理器警告的情况下,在后台线程中查找文本大小
- 缓存渲染文本位图以提高性能
- 自定义属性交互处理(链接点击等)
安装
只需将 StyledTextKit
添加到您的 Podfile 中并安装即可。完成!
pod 'StyledTextKit'
使用
NSAttributedString
构建 StyledTextKit
允许您构建复杂的 NSAttributedString
- 在重用字符串当前属性的同时附加
NSAttributedString
或String
,从而节省您反复使用.font
和.foregroundColor
进行样式的重复操作。 - 混合复杂的字体特性,如 粗体 和 斜体,以形成 粗斜体。
- 处理字符串渲染时的动态文本大小。允许您一次性构建字符串,并在设备文本大小变化时重新渲染。
- 调用
save()
和restore()
来推送/弹出样式设置,从而在不编写复杂代码的情况下构建复杂的文本样式。
let attributedString = StyledTextBuilder(text: "Foo ")
.save()
.add(text: "bar", traits: [.traitBold])
.restore()
.add(text: " baz!")
.build()
.render(contentSizeCategory: .large)
Foo bar baz!
基本步骤是
- 创建一个
StyledTextBuilder
- 添加
StyledText
对象 - 完成时调用
build()
来生成一个StyledTextString
对象 - 调用
render(contentSizeCategory:)
以创建一个NSAttributedString
渲染文本位图
通过用 StyledTextString
和 UIContentSizeCategory
初始化来为尺寸和渲染创建一个 StyledTextRenderer
let renderer = StyledTextRenderer(
string: string,
contentSizeCategory: .large
)
创建后,您可以轻松获取约束在一定宽度内文本的大小
let size = renderer.size(in: 320)
您还可以获取文本的位图
let result = renderer.render(for: 320)
view.layer.contents = result.image
StyledTextView
要简化 UIView
中的文本渲染和布局,请使用 StyledTextView
来管理显示和交互。您只需要一个 StyledTextRenderer
和一个宽度即可!
let view = StyledTextView()
view.configure(with: renderer, width: 320)
设置视图的代理以处理点击和长按
view.delegate = self
// StyledTextViewDelegate
func didTap(view: StyledTextView, attributes: [NSAttributedStringKey: Any], point: CGPoint) {
guard let link = attributes[.link] else { return }
show(SFSafariViewController(url: link))
}
后台渲染
StyledTextKit
存在是为了在后台对文本内容进行尺寸和渲染,以便平滑地滚动大量文本。执行此操作的典型流程是
- 获取当前宽度和
UIContentSizeCategory
- 转到后台队列
- 构建文本
- 预热缓存
- 返回主队列
- 配置您的视图
// ViewController.swift
let width = view.bounds.width
let contentSizeCategory = UIApplication.shared.preferredContentSizeCategory
DispatchQueue.global().async {
let builder = StyledTextBuilder(...)
let renderer = StyledTextRenderer(string: builder.build(), contentSizeCategory: contentSizeCategory)
.warm(width: width) // warms the size cache
DispatchQueue.main.async {
self.textView.configure(with: renderer, width: width)
}
}
常见问题问答
为什么不用
UITextView
?
在 iOS 7 之前,UITextView
在底层数据上使用 WebKit,速度极慢。现在它使用了 TextKit,速度显著提高,但仍需要在主线程上完成所有尺寸和渲染操作。
对于包含大量文本的 UITableViewCell
或 UICollectionViewCell
的应用,UITextView
会使滚动陷入停顿。
致谢
- @ocrickard,他构建了ComponentTextKit并教会了我基础知识。
- 由以下工具创建
❤️ 由Ryan Nystrom提供