如何使NSAttributedString的下划线样式属性起作用?

时间:2018-11-05 07:16:53

标签: ios swift nsattributedstring

我要使用NSAttributedString在字符串的下划线下划线。以下代码无法正常工作:

let string = NSMutableAttributedString(string: "This is my string.")

string.addAttributes([.underlineStyle : NSUnderlineStyle.single], 
                           range: NSRange(location: 5, length: 2))

有人希望在“是”下划线。相反,UITextView布局引擎将忽略该属性,并在控制台中生成警告。该警告无助地没有提及underlineStyleNSUnderlineStyle

这个问题很常见。 StackOverflow上有很多示例显示了正确的用法。但是,虽然我确定必须有一些答案可以解释该问题,但我已阅读的答案仅显示了用法的不透明示例。

提出这个问题(并在下面给出答案)是为了纪念对该问题的解释,以便将来我和其他人可以从中学习。

1 个答案:

答案 0 :(得分:3)

NSUnderlineStyle不是正确的类型

documentation准确但有些无用,它说明underlineStyle属性键采用的属性值为“ NSNumber,其中包含整数”。

  

此属性的值是一个NSNumber对象,其中包含一个   整数。此值指示文本是否带下划线,以及   对应于NSUnderlineStyle中描述的常量之一。的   此属性的默认值为styleNone。

许多读者被吸引到NSUnderlineStyle上,单击它,然后找到类似枚举的样式列表:singlethickpatternDash,{{1} }等。这似乎是一个很好的Swifty解决方案。读者认为此枚举必须是指定属性值的方式,并键入上面问题中显示的代码种类。


double的{​​{1}}属性提供了正确的类型

rawValue不是一个枚举。它是符合NSUnderlineStyle协议的结构。 NSUnderlineStyle协议是一种方便,快捷的方式来设置整数的位,每个位代表一个二进制状态。 OptionSet结构是该整数的包装器。它的类似于枚举的样式实际上是该结构上的静态var,每个静态var返回带有嵌入式整数的OptionSet实例,并且只有一位翻转以对应于所需样式。

NSUnderlineStyle的属性字典实际上将任何内容作为值,因此它很高兴地接受NSUnderlineStyle的实例。但是使NSAttributedStringNSUnderlineStyle工作的引擎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的互操作,IntNSNumber包装在NSNumber内。无需(或受益于?)将NSAttributedString明确地包装在Int中。


使用NSNumber Int方法合并下划线样式

我们可以将多个下划线样式组合成一个复合样式。在按位级别上,这是通过对代表两种样式的整数进行逻辑或来实现的。作为NSNumberOptionSet提供了一种Swifty替代方案。 union上的OptionSet方法以更简单的英语方式实现逻辑或。例如:

NSUnderlineStyle

此代码将产生一个union(_:),并翻转了相应的位,然后TextKit绘制了一个非常漂亮的虚线双下划线。当然,并非所有组合都可以。 'NSAttributedString'可以接受任何内容,但是常识和NSUnderlineStyle引擎最终将决定。