Добавление атрибутов в строку с помощью смайликов нарушает некоторые смайлики
Когда я пытаюсь добавить атрибуты к атрибутной строке, которая содержит эмодзи, иногда некоторые смайлики нарушаются. Для обычного текста работает отлично. Есть идеи, что я делаю не так?
Вот моя функция - она должна выделять жирным шрифтом цитаты (текст между первой и последней кавычкой)
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 = "\"\""
Результат выглядит так:
Я использую Swift 2.3, iOS 10.2.1, Xcode 8.2.1, цель развертывания: 9.3
1 ответ
Хорошо, после дальнейшего исследования (и без ответа) я наконец нашел причину и решение этой ошибки.
Возникла проблема с созданием NSRange
используя индексы Range
(получен из String
). Короче говоря - Свифт 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))
Так каково правильное решение? Сначала преобразуйте строку в строку 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 от Swift Range