Проверка подстроки в Swift: полный гайд с примерами кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как проверить, содержит ли строка подстроку в Swift? Полное руководство

Привет, коллега-разработчик! Если ты когда-нибудь писал на Swift и задавался вопросом: «Как же мне найти одно слово внутри другого?», — ты попал по адресу. Эта тема — один из самых популярных вопросов на Stack Overflow (английская версия набрала сотни тысяч просмотров). И это не случайно: работа со строками — база, без которой не обходится ни одно приложение.

В этой статье мы разберём все легальные способы проверить, содержит ли строка подстроку. От простейшего contains() до продвинутых техник с регистронезависимым поиском и регулярными выражениями. Поехали!

1. Самый простой способ: метод contains()

Начиная с Swift 1.0, у нас есть встроенный метод contains() у типа String. Он работает интуитивно и очень быстро.

let fullString = "Привет, мир Swift!"
let searchString = "Swift"

if fullString.contains(searchString) {
    print("Да, строка содержит '\(searchString)'")
} else {
    print("Нет, не содержит")
}
// Вывод: Да, строка содержит 'Swift'

Важно: метод contains() чувствителен к регистру. То есть "swift" не будет найден в строке "Swift". Но мы это исправим чуть позже.

2. Регистронезависимый поиск: localizedCaseInsensitiveContains()

Часто нужно найти слово, не обращая внимания на заглавные буквы. Для этого есть специальный метод, который работает с учётом локали пользователя.

let text = "Добро пожаловать в Swift"
let search = "swift"

if text.localizedCaseInsensitiveContains(search) {
    print("Найдено! Регистр не помеха.")
} else {
    print("Не найдено")
}
// Вывод: Найдено! Регистр не помеха.

Этот метод использует текущую локаль устройства, что особенно важно для языков с особыми правилами сравнения (например, турецкий, где «i» и «I» — разные буквы).

3. Поиск с учётом локали: localizedStandardContains()

Ещё один полезный метод — localizedStandardContains(). Он выполняет поиск так, как это делает стандартный поиск в iOS (например, в Spotlight или Finder).

let fileName = "Фото_отпуска_2024.jpg"
let query = "отпуска"

if fileName.localizedStandardContains(query) {
    print("Файл найден!")
}
// Вывод: Файл найден!

Этот метод автоматически нормализует строки, убирает диакритические знаки (например, «ё» = «е») и работает регистронезависимо. Идеально для поисковых строк в интерфейсе.

4. Классический способ: range(of:)

Иногда нужно не просто узнать, есть ли подстрока, но и получить её позицию. Тут на помощь приходит range(of:). Он возвращает опциональный диапазон (Range<String.Index>?).

let phrase = "Изучаем Swift на pythonlib.ru"
let word = "Swift"

if let range = phrase.range(of: word) {
    print("Подстрока найдена на позиции: \(range.lowerBound)")
    // Можно даже извлечь кусок строки
    let extracted = phrase[range]
    print("Извлечено: \(extracted)")
} else {
    print("Подстрока не найдена")
}

Для регистронезависимого поиска с range используйте опцию .caseInsensitive:

if let range = phrase.range(of: "swift", options: .caseInsensitive) {
    print("Найдено без учёта регистра: \(phrase[range])")
}

5. Проверка начала и конца строки

Иногда нужно проверить не «содержит ли вообще», а «начинается ли с...» или «заканчивается ли на...». Для этого есть специальные методы:

let url = "https://pythonlib.ru"

if url.hasPrefix("https://") {
    print("Это безопасный URL")
}

if url.hasSuffix(".ru") {
    print("Российский домен")
}

Оба метода тоже чувствительны к регистру. Для регистронезависимой версии придётся привести обе строки к одному регистру вручную:

if url.lowercased().hasPrefix("HTTPS://".lowercased()) {
    print("Регистронезависимая проверка сработала")
}

6. Продвинутый поиск: регулярные выражения (NSRegularExpression)

Когда простого поиска недостаточно (например, нужно найти все email'ы или номера телефонов), в дело вступают регулярные выражения. В Swift для этого используется NSRegularExpression.

let text = "Мой email: test@example.com, а также admin@site.org"
let pattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

do {
    let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
    let matches = regex.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
    
    for match in matches {
        if let range = Range(match.range, in: text) {
            print("Найден email: \(text[range])")
        }
    }
} catch {
    print("Ошибка в регулярном выражении: \(error.localizedDescription)")
}

Важно: работа с NSRegularExpression требует перехода к NSRange и обратно к Range<String.Index>. Это не очень удобно, но даёт огромную гибкость.

7. Альтернативный подход: NSString bridge

Swift-строки могут быть «мостом» к Objective-C строке NSString. Это даёт доступ к старым, но проверенным методам, таким как contains() с опциями.

let swiftString = "Swift — это мощно!"
let nsString = swiftString as NSString

if nsString.contains("мощно") {
    print("Метод NSString тоже работает")
}

// Регистронезависимая версия
if nsString.range(of: "СВИФТ", options: .caseInsensitive).location != NSNotFound {
    print("Найдено через NSString с игнором регистра")
}

Однако я рекомендую использовать нативные Swift-методы, если нет необходимости в обратной совместимости.

8. Производительность: что выбрать?

В большинстве случаев contains() — самый быстрый и читаемый вариант. Если нужен регистронезависимый поиск — localizedCaseInsensitiveContains. Для поиска с нормализацией — localizedStandardContains.

Регулярные выражения — мощный, но медленный инструмент. Используйте их только для сложных шаблонов, а не для простого поиска фиксированной подстроки.

9. Практический пример: поиск в списке строк

Часто нужно отфильтровать массив строк по подстроке. Вот как это делается элегантно:

let fruits = ["Яблоко", "Апельсин", "Банан", "Авока                

Блоги

Рекомендаций по книгам