使用emojis向字符串添加属性会破坏一些表情符号

时间:2017-02-04 00:20:10

标签: ios nsattributedstring emoji

当我尝试将属性添加到包含表情符号的属性字符串时,有时会破坏某些表情符号。对于常规文本工作完美。我有什么想法吗?

这是我的功能 - 它应该是粗体引号(第一个和最后一个引号之间的文字)

func boldQuotation(str: String, fontSize: CGFloat) -> NSAttributedString {
    let normalAttributes = [NSFontAttributeName : UIFont.systemFontOfSize(fontSize)]
    let boldAttributes = [NSFontAttributeName : UIFont.boldSystemFontOfSize(fontSize)]
    let attributedStr = NSMutableAttributedString(string: str, attributes: normalAttributes)

    let firstQuotationMarkRange = str.rangeOfString("\"")
    let lastQuotationMarkRange  = str.rangeOfString("\"", options: [.BackwardsSearch], range: nil, locale: nil)
    guard let firstIndex = firstQuotationMarkRange?.startIndex, lastIndex = lastQuotationMarkRange?.endIndex else {
        return attributedStr
    }
    attributedStr.addAttributes(boldAttributes, range: NSMakeRange(str.startIndex.distanceTo(firstIndex), firstIndex.distanceTo(lastIndex)))
    return attributedStr
}

以下是无法正确归因的文字示例:

let str = "\"\""

结果如下:

works in Postgres 9.6

我使用的是Swift 2.3,iOS 10.2.1,Xcode 8.2.1,部署目标:9.3

1 个答案:

答案 0 :(得分:-1)

好的,经过进一步的调查(没有回答),我终于找到了那个错误的原因和解决方案。

使用NSRange索引(从Range获取)创建String时出现问题。长话短说 - Swift String范围和NSString范围不应该用于将一个范围转换为另一个范围。至少不是这样的:

let firstQuotationMarkRange     = str.rangeOfString("\"")
let lastQuotationMarkRange      = str.rangeOfString("\"", options: [.BackwardsSearch], range: nil, locale: nil)
guard let firstIndex = firstQuotationMarkRange?.startIndex, lastIndex = lastQuotationMarkRange?.endIndex else {
        return attributedStr
    }
//THIS IS WRONG:
range = NSMakeRange(str.startIndex.distanceTo(firstIndex), firstIndex.distanceTo(lastIndex))

那么什么是正确的解决方案?首先将String转换为NSString,然后开始查找子串范围。这是固定功能:

func boldQuotation(str: String, fontSize: CGFloat) -> NSAttributedString {
    let normalAttributes = [NSFontAttributeName : UIFont.systemFontOfSize(fontSize)]
    let boldAttributes = [NSFontAttributeName : UIFont.boldSystemFontOfSize(fontSize)]
    let attributedStr = NSMutableAttributedString(string: str, attributes: normalAttributes)

    let nsStr = str as NSString
    let firstQuotationMarkRange = nsStr.rangeOfString("\"")
    let lastQuotationMarkRange  = nsStr.rangeOfString("\"", options: [.BackwardsSearch])
    guard firstQuotationMarkRange.length > 0 && lastQuotationMarkRange.length > 0 else {
        return attributedStr
    }
    let nsrange = NSMakeRange(firstQuotationMarkRange.location, lastQuotationMarkRange.location + lastQuotationMarkRange.length - firstQuotationMarkRange.location)
    attributedStr.addAttributes(boldAttributes, range: nsrange)
    return attributedStr
}

感谢此帖:NSRange from Swift Range