Короче говоря: при использовании Swift с String
и NSRange
используйте это расширение для преобразования диапазона
extension String {
/// Fixes the problem with `NSRange` to `Range` conversion
var range: NSRange {
let fromIndex = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: 0)
let toIndex = unicodeScalars.index(fromIndex, offsetBy: count)
return NSRange(fromIndex..<toIndex, in: self)
}
}
Давайте рассмотрим подробнее:
let myStr = "Wéll helló ⚙️"
myStr.count // 12
myStr.unicodeScalars.count // 13
myStr.utf8.count // 19
myStr.utf16.count // 13
In Swift 4 строка представляет собой набор символов (составной символ, такой как ö , и смайлики будут считаться одним символом). UTF-8 и UTF-16 - это наборы кодовых единиц UTF-8 и UTF-16 соответственно.
Ваша проблема в том, что textView.text.count считает элементы коллекции (эмодзи, а также составной символ будет считаться одним элементом), а NSRange
подсчитывает индексы кодовых единиц UTF-16.Разница проиллюстрирована во фрагменте выше.
Подробнее здесь: Строки и символы