Swift:NSAttributedString和表情符号

时间:2019-06-06 03:59:53

标签: ios swift nsattributedstring emoji nsrange

我使用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}:示例文本

     

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

1 个答案:

答案 0 :(得分:1)

使用NSAttributedStringNSRangeString时要记住的最重要的事情是NSAttributedString(和NSString)和{{1} }基于UTF-16编码的长度。但是NSRange及其String是基于实际字符数的。他们不会混在一起。

如果您尝试使用count创建一个NSRange,则会得到错误的范围。始终使用someSwiftString.count

在特定情况下,由于someSwiftString.utf16.count中的长度错误,您正在将❤️字符的属性应用到一半,并且级联到您看到的错误。

在您发布的代码中,您需要更改:

NSRange

收件人:

guard (range.location + range.length - 1) < string.count else {

出于上述相同的原因。