- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
使用 NSAttributedString
,我想给字符串的一部分加下划线。以下代码未按预期工作:
let string = NSMutableAttributedString(string: "This is my string.")
string.addAttributes([.underlineStyle : NSUnderlineStyle.single],
range: NSRange(location: 5, length: 2))
人们希望"is"带有下划线。相反,UITextView 布局引擎会忽略该属性,并在控制台中生成警告。不幸的是,警告没有提及 underlineStyle
或 NSUnderlineStyle
。
这个问题很常见。 StackOverflow 上有大量显示正确用法的示例。然而,虽然我确信一定有一些答案可以解释这个问题,但我读过的答案仅显示了不透明的用法示例。
提出这个问题(并在下面给出答案)是为了纪念对问题的解释,以便 future 的我和其他人可以从中学习。
最佳答案
NSUnderlineStyle
不是正确的类型准确地说,但有点无益,documentation解释了 underlineStyle
属性键采用“包含整数的NSNumber
”的属性值。
The value of this attribute is an NSNumber object containing an integer. This value indicates whether the text is underlined and corresponds to one of the constants described in NSUnderlineStyle. The default value for this attribute is styleNone.
许多读者被 NSUnderlineStyle
吸引,点击它,找到一个类似枚举的样式列表:single
、thick
、patternDash
、double
等。这似乎都是一个很好的 Swifty 解决方案。读者凭直觉认为此枚举必须是指定属性值的方式,并键入上面问题中显示的那种代码。
NSUnderlineStyle
的 rawValue
属性提供了正确的类型NSUnderlineStyle
不是枚举。它是一个符合 OptionSet
协议(protocol)的结构。 OptionSet
协议(protocol)是一种方便快捷的整数位设置方式,每个位代表一个二进制状态。 NSUnderlineStyle
结构是该整数的包装器。它的类似枚举的样式实际上是结构上的静态变量,每个变量都返回一个带有嵌入整数的 NSUnderlineStyle
实例,其中只有一个位被翻转以对应于所需的样式。
NSAttributedString
的属性字典几乎可以接受任何东西作为值,所以它很乐意接受 NSUnderlineStyle
的实例。但是,使 UITextView
和 UILabel
工作的引擎 TextKit 不知道如何处理 NSUnderlineStyle
实例。当 TextKit 尝试呈现 underlineStyle
属性时,它需要一个整数,以便它可以通过检查整数的位来确定正确的样式。
幸运的是,有一种简单的方法可以获取该整数。 NSUnderlineStyle
的 rawValue
属性提供了它。因此,我们的代码片段的正确工作版本如下:
let string = NSMutableAttributedString(string: "This is my string.")
string.addAttributes([.underlineStyle : NSUnderlineStyle.single.rawValue],
range: NSRange(location: 5, length: 2))
此代码与问题中的代码之间的唯一区别是将“.rawValue”添加到“NSUnderlineStyle.single”。并且,"is"带有下划线。
作为旁注,rawValue
属性提供的类型是 Int
,而不是 NSNumber
。文档对作为 NSNumber
的属性值的引用可能会造成混淆。在底层,为了与 ObjC 互操作,NSAttributedString
将 Int
包装在 NSNumber
中。没有必要(或有益于?)在 NSNumber
中显式包装 Int
。
OptionSet
union
方法组合下划线样式我们可以将多个下划线样式组合在一起成为一个复合样式。在逐位级别,这是通过对表示两种样式的整数进行逻辑或来实现的。作为一个 OptionSet
,NSUnderlineStyle
提供了一个 Swifty 替代方案。 NSUnderlineStyle
上的 union(_:)
方法以更通俗易懂的方式实现逻辑或。例如:
NSUnderlineStyle.double.union(.patternDot).rawValue
这段代码产生了一个 Int
并翻转了适当的位,TextKit 绘制了一个非常漂亮的点状双下划线。当然,并非所有组合都有效。 'NSAttributedString' 可以接受任何东西,但常识和 TextKit
引擎最终会决定。
关于ios - 如何让 NSAttributedString 的下划线样式属性起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53149864/
我是一名优秀的程序员,十分优秀!