Как правило, вы должны использовать нативные типы Swift настолько, насколько это возможно, потому что они оптимизированы для компиляции для повышения производительности. Но подождите, я только что сказал неизбежно, верно? В качестве примера рассмотрим основанный на Objective-C класс NSRegularExpression.

let str = "Hello, playground"
do {
    let expression = try NSRegularExpression(pattern: "\\s{1,}",
                                             options: [.anchorsMatchLines])
    let range = NSRange(location: 0,
                        length: str.characters.count)
    let matches = expression.matches(in: str,
                                     options: [],
                                     range: range)
    for match in matches {
        print(match)
    }
} catch  {
    print(error.localizedDescription)
}

В приведенном выше фрагменте мы видим функцию func matches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> [NSTextCheckingResult], которая принимает только переменную NSRange в качестве параметра; поэтому перевод Range типа str.startIndex..<str.endIndex в класс NSRange несомненно будет необходим, как только наши коды будут взаимодействовать и смешаны String, NSString, Range и NSRange. Однако опытный программист на Swift может обнаружить, что в приведенном выше фрагменте тоже есть смертельный недостаток. Речь идет о способе вычисления длины строки, str.characters.count. Такая практика очень подвержена ошибкам, поскольку Swift использует расширенные кластеры Grapheme. Ex, символ смайлика Unicode. Swift видит его как один символ, но метод NSString видит его как два.

Итак… есть принцип или предложение?

Если мы не хотим уделять слишком много внимания разнице, подобной этой, для безрискового, я предлагаю всегда преобразовывать String в NSString перед функцией на основе Objective-C, такой как NSRegularExpression. Конечно, в этой стратегии не будет необходимости, пока не будет введена собственная функция Swift, например. мы могли бы увидеть RegularExpression когда-нибудь.

Итак, для того, чтобы исправить вышеуказанный недостаток. Способ вычисления длины должен быть похож на приведенный ниже фрагмент. В общем, всегда есть нативные способы работы с переменными; однако безрисковая или менее подверженная ошибкам стратегия иногда может сэкономить нам день :)

// Option 1: Cast String to NSString
let range = NSRange(location: 0,
                    length: (str as NSString).length)

// Option 2: Calculate utf16 count when accessing on a Swift String value.
let range = NSRange(location: 0,
                    length: str.utf16.count)