Проблема: NSAttributedString принимает NSRange, в то время как я использую строку Swift, которая использует Range
let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)
text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
Выдает следующую ошибку:
ошибка: «Диапазон» не может быть преобразован в «NSRange» attribute.String.addAttribute (NSForegroundColorAttributeName, значение: NSColor.redColor (), диапазон: substringRange)
Ответы:
Быстрые
String
диапазоны иNSString
диапазоны не являются «совместимыми». Например, смайлик типа 😄 считается одним символом Свифта, но двумяNSString
символами (так называемая суррогатная пара UTF-16).Поэтому предложенное вами решение даст неожиданные результаты, если строка содержит такие символы. Пример:
Вывод:
Как видите, «ph say» был помечен атрибутом, а не «say».
Так как в
NS(Mutable)AttributedString
конечном итоге требуются anNSString
и anNSRange
, на самом деле лучше преобразовать данную строку вNSString
первую. ТогдаsubstringRange
этоNSRange
и вам больше не нужно конвертировать диапазоны:Вывод:
Обновление для Swift 2:
Обновление для Swift 3:
Обновление для Swift 4:
Начиная с Swift 4 (Xcode 9), стандартная библиотека Swift предоставляет метод для преобразования между
Range<String.Index>
иNSRange
. Преобразование вNSString
больше не нужно:Вот
substringRange
этоRange<String.Index>
, и что превращают в соответствующееNSRange
систочник
Range<String.Index>
иNSString
не совместимы. Их аналоги также несовместимы? То естьNSRange
иString
несовместимы? Потому что один из API Apple специально объединяет два: совпадения (в: options: range :)Для случаев, подобных тому, который вы описали, я обнаружил, что это работает. Это относительно коротко и сладко:
источник
NSRange
.str
являетсяNSString
и, следовательно,str.RangeOfString()
возвращаетNSRange
.let str = attributedString.string as NSString
Ответы хороши, но с Swift 4 вы можете немного упростить ваш код:
Будьте осторожны, так как результат
range
функции должен быть развернут.источник
Возможное решение
Swift предоставляет distance (), который измеряет расстояние между началом и концом, которое можно использовать для создания NSRange:
источник
Для меня это работает отлично:
источник
Свифт 4:
Конечно, я знаю, что Swift 4 уже имеет расширение для NSRange
Я знаю, что в большинстве случаев этого достаточно. Смотрите его использование:
Но преобразование может быть выполнено непосредственно из Range <String.Index> в NSRange без экземпляра Swift String.
Вместо общего использования init, которое требует от вас целевого параметра как String, и если у вас нет целевой строки под рукой, вы можете создать преобразование напрямую
или вы можете создать специализированное расширение для самого Range
Использование:
или
Свифт 5:
Из-за миграции строк Swift в кодировку UTF-8 по умолчанию использование
encodedOffset
считается устаревшим, и Range нельзя преобразовать в NSRange без экземпляра самой String, поскольку для вычисления смещения нам нужна исходная строка, которая является закодированы в UTF-8 и должны быть преобразованы в UTF-16 перед вычислением смещения. Так что лучший подход на данный момент - использовать общий init .источник
encodedOffset
является считается вредным и будет устаревшим .Swift 4
Я думаю, что есть два пути.
1. NSRange (диапазон, в:)
2. NSRange (местоположение :, длина:)
Образец кода:
Скриншот:
источник
encodedOffset
является считается вредным и будет устаревшим .Вариант расширения Swift 3, который сохраняет существующие атрибуты.
источник
источник
Я люблю язык Swift, но использование
NSAttributedString
с SwiftRange
, которое не совместимо сNSRange
, заставило мою голову болеть слишком долго. Таким образом, чтобы обойти весь этот мусор, я разработал следующие методы, чтобы вернутьNSMutableAttributedString
с выделенными словами, установленными с вашим цветом.Это не работает для смайликов. Изменить, если необходимо.
Использование:
источник
источник