将iOS 5的NSAttributedString 迁移回来,以便您可以在 Interface Builder 中使用高亮文本 UILabel。(实验性)
NSAttributedString UIKit 扩展在iOS 6中新引入。它赋予开发者将 NSAttributedString 指定到常见 UI 元素(如 UILabel、UIButton 等)中的能力,而无需深入研究复杂的 CoreText API。
虽然已经有一些如 TTTAttributedLabel、RTLabel、OHAttributedLabel等库。所有这些库都非常强大,支持各种标记,但我找不到一个能够桥接缺失部分的库——在 iOS 5 中直接将 NSAttributedString 指定到 Interface Builder 中的 UILabel。而 JTAttributedLabel 就是这样尝试恢复缺失部分的工程。
在 Interface Builder 中,如果您在 UILabel 中指定了 NSAttributedString,SDK 足够聪明,可以使视图配置与 iOS 5 兼容,但返回的是纯文本文本布局。
对我来说的第一个问题是,我们如何从置于 Interface Builder 中的 UILabel 中提取 NSAttributedString。iOS 5 的 UILabel 类中没有 attributedText
属性。我记得 UI 元素在由操作系统初始化后会被调用一次 initWithCoder:
方法,我相信我可以在某个地方找到隐藏的 attributedText
。
NSCoder
不像 NSDictionary
,我们可以简单地使用 NSLog 来打印出封装的属性。感谢 @nicklockwood 提供的提示,使用 NSProxy
,我可以创建一个简单的 NSProxy 子类 来封装 NSCoder
对象,看看 iOS 6 如何处理它。在那里我发现“UIAttributedText”键。
手头有了 attributedText,我立即尝试将它分配给那些丰富文本的 UILabel 库。我以为这很简单,但后来它导致 CoreText API 中出现神秘的崩溃。经过一番调查,我发现 NSAttributedString 的底层实现稍有不同。iOS 6 好像包含一个新类 NSParagraphStyle
,它保存文本属性。通过借鉴 @hlfcoding 在 RRAutoLayout 介绍中的技术,我能够条件性地在运行时实现 NSParagraphStyle
,如下所示:
if( ! NSClassFromString(@"NSParagraphStyle") ){
objc_registerClassPair(objc_allocateClassPair([JTParagraphStyle class], "NSParagraphStyle", 0));
}
因此,它与CoreText库的数据结构不同。我意识到我需要将iOS 6的NSAttributeString转换为iOS 5兼容的版本,在那里我发现了一些在“已知的错误”中说明的无法映射的特性。
经过这一切,我创建了一个继承自UILabel
并具有CATextLayer
的子类来布局NSAttributeString。现在我们有一个轻量但并不完美的实现。
将所有头文件和实现文件放入你的项目的JTAttributedLabel/JTAttributedLabel目录中。
在你的Interface Builder中,拖入一个UILabel并将它的子类指定为JTAttributedLabel
或JTAutoLabel
。
JTAttributedLabel
和JTAutoLabel
之间的区别是后者将自动使用iOS 6默认的UILabel
类以实现最佳显示效果。
还有一些非常流行的库将iOS 6的特性带到了iOS 5上。
祝您享受,并请随意分支和评论!
JTAttributedLabel遵循MIT许可证,由James Tang创建 @mystcolor