我使用启用了文本属性编辑的UITextView
,在文本中含有表情符号时,获取属性存在问题。
这是我使用的代码:
var textAttributes = [(attributes: [NSAttributedString.Key: Any], range: NSRange)]()
let range = NSRange(location: 0, length: textView.attributedText.length)
textView.attributedText.enumerateAttributes(in: range) { dict, range, _ in
textAttributes.append((attributes: dict, range: range))
}
for attribute in textAttributes {
if let swiftRange = Range(attribute.range, in: textView.text) {
print("NSRange \(attribute.range): \(textView.text![swiftRange])")
} else {
print("NSRange \(attribute.range): cannot convert to Swift range")
}
}
当我使用"Sample text ❤️"这样的文本进行尝试时,输出如下:
NSRange {0, 12}: Sample text NSRange {12, 1}: 无法转换为Swift范围 NSRange {13, 1}: 无法转换为Swift范围
所以你可以看到,我无法获取带有表情符号的文本。
文本属性由我自定义的NSTextStorage应用于文本视图来设置。这是setAttributes方法:
override func setAttributes(_ attrs: [NSAttributedString.Key: Any]?, range: NSRange) {
guard (range.location + range.length - 1) < string.count else {
print("Range out of bounds")
return
}
beginEditing()
storage.setAttributes(attrs, range: range)
edited(.editedAttributes, range: range, changeInLength: 0)
endEditing()
}
请注意,在编辑我的文本视图时,我会看到一些“范围超出界限”的打印信息。
是否有一种方法将NSRange转换为有效的Swift Range?
Range(attribute.range, in: textView.text)
进行转换。 - rmaddyguard (range.location + range.length - 1) < string.count else {
修改为guard (range.location + range.length - 1) < string.utf16.count else {
。 - rmaddystring.utf16.count
很有效!但是,转换为 SwiftRange
仍然会显示“无法转换为 Swift 范围”。我成功地使用了textView.attributedText.attributedSubstring(from: attribute.range).string
来进行子字符串操作。 - FlorentinString
计数的NSRange
,但是这是错误的。在从String
创建NSRange
时,它必须始终为.utf16.count
。因此,请再次展示如何将属性应用于属性文本(并展示如何创建范围)。 - rmaddy.count
改为了.utf16.count
在NSRange
中,现在它按预期工作了! - Florentin