我要使用NSAttributedString
在字符串的下划线下划线。以下代码无法正常工作:
let string = NSMutableAttributedString(string: "This is my string.")
string.addAttributes([.underlineStyle : NSUnderlineStyle.single],
range: NSRange(location: 5, length: 2))
有人希望在“是”下划线。相反,UITextView布局引擎将忽略该属性,并在控制台中生成警告。该警告无助地没有提及underlineStyle
或NSUnderlineStyle
。
这个问题很常见。 StackOverflow上有很多示例显示了正确的用法。但是,虽然我确定必须有一些答案可以解释该问题,但我已阅读的答案仅显示了用法的不透明示例。
提出这个问题(并在下面给出答案)是为了纪念对该问题的解释,以便将来我和其他人可以从中学习。
答案 0 :(得分:3)
NSUnderlineStyle
不是正确的类型 documentation准确但有些无用,它说明underlineStyle
属性键采用的属性值为“ NSNumber
,其中包含整数”。
此属性的值是一个NSNumber对象,其中包含一个 整数。此值指示文本是否带下划线,以及 对应于NSUnderlineStyle中描述的常量之一。的 此属性的默认值为styleNone。
许多读者被吸引到NSUnderlineStyle
上,单击它,然后找到类似枚举的样式列表:single
,thick
,patternDash
,{{1} }等。这似乎是一个很好的Swifty解决方案。读者认为此枚举必须是指定属性值的方式,并键入上面问题中显示的代码种类。
double
的{{1}}属性提供了正确的类型 rawValue
不是一个枚举。它是符合NSUnderlineStyle
协议的结构。 NSUnderlineStyle
协议是一种方便,快捷的方式来设置整数的位,每个位代表一个二进制状态。 OptionSet
结构是该整数的包装器。它的类似于枚举的样式实际上是该结构上的静态var,每个静态var返回带有嵌入式整数的OptionSet
实例,并且只有一位翻转以对应于所需样式。
NSUnderlineStyle
的属性字典实际上将任何内容作为值,因此它很高兴地接受NSUnderlineStyle
的实例。但是使NSAttributedString
和NSUnderlineStyle
工作的引擎TextKit不知道如何处理UITextView
实例。当TextKit尝试呈现UILabel
属性时,它需要一个整数,以便可以通过检查整数的位来确定正确的样式。
幸运的是,有一种简单的方法可以获取该整数。 NSUnderlineStyle
的{{1}}属性对其进行出售。因此,我们的代码段的正常工作版本如下:
underlineStyle
此代码与问题代码之间的唯一区别是在“ NSUnderlineStyle.single”上添加了“ .rawValue”。并且,“ is”带有下划线。
请注意,rawValue
属性提供的类型是NSUnderlineStyle
,而不是let string = NSMutableAttributedString(string: "This is my string.")
string.addAttributes([.underlineStyle : NSUnderlineStyle.single.rawValue],
range: NSRange(location: 5, length: 2))
。文档对属性值为rawValue
的引用可能会造成混淆。为了实现与ObjC的互操作,Int
将NSNumber
包装在NSNumber
内。无需(或受益于?)将NSAttributedString
明确地包装在Int
中。
NSNumber
Int
方法合并下划线样式我们可以将多个下划线样式组合成一个复合样式。在按位级别上,这是通过对代表两种样式的整数进行逻辑或来实现的。作为NSNumber
,OptionSet
提供了一种Swifty替代方案。 union
上的OptionSet
方法以更简单的英语方式实现逻辑或。例如:
NSUnderlineStyle
此代码将产生一个union(_:)
,并翻转了相应的位,然后TextKit绘制了一个非常漂亮的虚线双下划线。当然,并非所有组合都可以。 'NSAttributedString'可以接受任何内容,但是常识和NSUnderlineStyle
引擎最终将决定。