🍎 Swift

Métodos de String — Guia Completo em Swift: Um Guia Detalhado

Что это такое и зачем? (аналогия из реальной жизни)

Представь, что ты — библиотекарь. У тебя есть огромное количество книг (строк). Каждая книга — это просто набор букв, но ты можешь с ней делать разные полезные вещи:

  • Найти, есть ли в книге слово "приключения"
  • Заменить старое название на новое
  • Разрезать книгу на главы
  • Посчитать, сколько букв "а" в тексте
  • Сделать все буквы заглавными для обложки

В программировании строки — это тот же текст. А методы строк — это готовые инструменты (как ножницы, лупа или клей), которые Swift даёт тебе в руки, чтобы ты мог управлять текстом, не изобретая велосипед.

💡 Важно: Строка в Swift — это не просто набор символов. Это сложная структура, которая умеет делать много полезного сама, без твоей помощи. Твоя задача — только попросить её об этом.

Теория: как это работает изнутри

Давай заглянем под капот. Когда ты пишешь "Привет, мир!", Swift создаёт в памяти специальный объект — String. Этот объект хранит не просто буквы, а целую коллекцию символов (Character).

Каждый символ может быть:

  • Буквой (A, б, Я)
  • Цифрой (1, 2, 3)
  • Знаком препинания (., !, ?)
  • Эмодзи (😀, 🚀)
  • Пробелом

Но самое интересное — Swift хранит строку особым образом. Он использует Unicode — международный стандарт, который позволяет хранить текст на любом языке мира: русском, китайском, арабском. Поэтому одна и та же буква "ё" может быть записана двумя способами: как один символ или как буква "е" + две точки. Swift это учитывает!

Методы строк — это встроенные функции, которые прикреплены к каждой строке. Ты вызываешь их через точку:

// Общий синтаксис:
// строка.имяМетода(параметры)

let имя = "Анна"
// Вызываем метод, который делает первую букву заглавной
let результат = имя.uppercased() 
print(результат) // "АННА"
⚠️ Запомни: Большинство методов строк не изменяют исходную строку, а возвращают новую. Оригинал остаётся нетронутым. Это называется иммутабельность (неизменяемость).

Синтаксис в Swift: все формы и варианты

Давай разберём все основные методы строк. Я разделил их на группы, чтобы было легче запомнить.

1. Изменение регистра

МетодЧто делаетПримерРезультат
uppercased()Все буквы заглавные"hello".uppercased()"HELLO"
lowercased()Все буквы строчные"HELLO".lowercased()"hello"
capitalizedПервая буква каждого слова заглавная"hello world".capitalized"Hello World"

2. Проверка содержимого

МетодЧто делаетПримерРезультат
isEmptyПроверяет, пустая ли строка"".isEmptytrue
contains("текст")Содержит ли строка указанный текст"Привет".contains("иве")true
hasPrefix("текст")Начинается ли с указанного текста"Свифт".hasPrefix("Св")true
hasSuffix("текст")Заканчивается ли указанным текстом"программирование".hasSuffix("ние")true

3. Поиск и замена

МетодЧто делаетПримерРезультат
replacingOccurrences(of: "что", with: "на что")Заменяет все вхождения"кот кот".replacingOccurrences(of: "кот", with: "пёс")"пёс пёс"
trimmingCharacters(in: .whitespaces)Удаляет пробелы в начале и конце" текст ".trimmingCharacters(in: .whitespaces)"текст"

4. Разделение и объединение

МетодЧто делаетПримерРезультат
split(separator: "символ")Разделяет строку на массив строк"a,b,c".split(separator: ",")["a", "b", "c"]
joined(separator: "разделитель")Объединяет массив строк в одну["a", "b"].joined(separator: "-")"a-b"

5. Доступ к символам

Метод/СвойствоЧто делаетПримерРезультат
countКоличество символов"Привет".count6
firstПервый символ (Optional)"Привет".first"П"
lastПоследний символ (Optional)"Привет".last"т"
🔑 Ключевой момент: В Swift нельзя просто взять символ по индексу, как в других языках. Нужно использовать специальные индексы строк (String.Index). Это связано с Unicode — символы могут занимать разное количество байт.

Примеры кода — от простого к сложному

Пример 1: Приветствие с заглавной буквы

// Самый простой пример — делаем первую букву заглавной
let имяПользователя = "мария"
// Используем метод capitalized — он делает заглавной первую букву каждого слова
let приветствие = "Привет, " + имяПользователя.capitalized + "!"
print(приветствие) // Выведет: "Привет, Мария!"

// Объяснение:
// 1. Создаём переменную с именем в нижнем регистре
// 2. Вызываем .capitalized — он возвращает новую строку "Мария"
// 3. Склеиваем три части: "Привет, " + "Мария" + "!"
// 4. Печатаем результат

Пример 2: Проверка пароля на сложность

// Проверяем, что пароль содержит хотя бы одну заглавную букву
let пароль = "Swift123"

// Используем метод contains для поиска подстроки
let содержитЗаглавную = пароль.contains("S") // true
let содержитЦифру = пароль.contains("1") // true

// Более умная проверка — ищем любую заглавную букву
let заглавныеБуквы = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var естьЗаглавная = false

// Перебираем каждую заглавную букву
for буква in заглавныеБуквы {
    if пароль.contains(буква) {
        естьЗаглавная = true
        break // Как нашли — выходим из цикла
    }
}

print("Пароль содержит заглавную букву: (естьЗаглавная)")
// Выведет: "Пароль содержит заглавную букву: true"

Пример 3: Очистка текста от лишних пробелов

// Пользователь ввёл текст с лишними пробелами
let грязныйТекст = "   Привет,   мир!   "

// Шаг 1: Удаляем пробелы в начале и конце
let безПробеловПоКраям = грязныйТекст.trimmingCharacters(in: .whitespaces)
print("После удаления пробелов по краям: '(безПробеловПоКраям)'")
// Выведет: "Привет,   мир!"

// Шаг 2: Заменяем множественные пробелы на один
// Разделяем строку по пробелам
let слова = безПробеловПоКраям.split(separator: " ")
print("Массив слов: (слова)") // ["Привет,", "мир!"]

// Шаг 3: Склеиваем обратно с одним пробелом
let чистыйТекст = слова.joined(separator: " ")
print("Чистый текст: '(чистыйТекст)'")
// Выведет: "Привет, мир!"

Пример 4: Поиск и замена в тексте

// Представь, что мы пишем цензуру для комментариев
let оригинал = "Этот фильм просто ужасный и отвратительный!"

// Список плохих слов
let плохиеСлова = ["ужасный", "отвратительный"]

// Создаём копию текста для изменений
var исправленныйТекст = оригинал

// Заменяем каждое плохое слово на звёздочки
for слово in плохиеСлова {
    // Создаём строку из звёздочек той же длины
    let замена = String(repeating: "*", count: слово.count)
    // Заменяем все вхождения плохого слова
    исправленныйТекст = исправленныйТекст.replacingOccurrences(of: слово, with: замена)
}

print("Оригинал: (оригинал)")
print("Исправлено: (исправленныйТекст)")
// Выведет: "Этот фильм просто ****** и **************!"

Пример 5: Работа с эмодзи и Unicode

// Swift отлично работает с эмодзи!
let приветствиеСЭмодзи = "Привет! 👋 Как дела? 😊"

// Считаем символы — эмодзи считается как один символ
print("Количество символов: (приветствиеСЭмодзи.count)")
// Выведет: 20 (каждый эмодзи — это один символ)

// Проверяем, содержит ли строка определённый эмодзи
let естьПомахивание = приветствиеСЭмодзи.contains("👋")
print("Есть помахивание: (естьПомахивание)") // true

// Получаем первый символ
if let первыйСимвол = приветствиеСЭмодзи.first {
    print("Первый символ: (первыйСимвол)") // "П"
}

// Получаем последний символ
if let последнийСимвол = приветствиеСЭмодзи.last {
    print("Последний символ: (последнийСимвол)") // "😊"
}

Пример 6: Разбор email-адреса

// Разбираем email на части
let email = "user@example.com"

// Проверяем, что это похоже на email
let содержитСобаку = email.contains("@")
let содержитТочку = email.contains(".")

if содержитСобаку && содержитТочку {
    print("Похоже на валидный email")
    
    // Разделяем по символу @
    let части = email.split(separator: "@")
    if части.count == 2 {
        let имяПользователя = String(части[0])
        let домен = String(части[1])
        
        print("Имя пользователя: (имяПользователя)") // "user"
        print("Домен: (домен)") // "example.com"
        
        // Проверяем домен верхнего уровня
        if домен.hasSuffix(".com") {
            print("Это коммерческий домен")
        }
    }
} else {
    print("Некорректный email")
}

Пример 7: Форматирование текста для вывода

// Создаём красивый вывод данных
let имя = "Алексей"
let возраст = 25
let город = "Москва"

// Используем многострочный литерал и интерполяцию
let профиль = """
    👤 Имя: (имя)
    🎂 Возраст: (возраст) лет
    📍 Город: (город)
    """

print(профиль)
// Выведет:
// 👤 Имя: Алексей
// 🎂 Возраст: 25 лет
// 📍 Город: Москва

// Дополнительно: выравнивание с помощью padding
let выровненныйТекст = "Имя".padding(toLength: 10, withPad: " ", startingAt: 0) + ": (имя)"
print(выровненныйТекст) // "Имя       : Алексей"

Сравнение с Python: чем похоже и чем отличается

Если ты уже знаешь Python или планируешь учить его потом, вот сравнение:

ОперацияSwiftPythonПримечание
Заглавные буквы"текст".uppercased()"текст".upper()Разные названия методов
Разделение строки"a,b".split(separator: ",")"a,b".split(",")В Python split возвращает список, в Swift — массив
Объединениемассив.joined(separator: "-")"-".join(массив)Синтаксис reversed!
Замена.replacingOccurrences(of: "a", with: "b").replace("a", "b")В Python метод называется replace
Проверка начала.hasPrefix("текст").startswith("текст")Разные названия
Проверка конца.hasSuffix("текст").endswith("текст")Разные названия
Длина строкистрока.countlen(строка)В Swift это свойство, в Python — функция
Доступ по индексустрока[строка.index(...)]строка[0]В Swift сложнее из-за Unicode
Срезы (substring)строка[диапазон]строка[1:3]В Swift нужно указывать тип String.Index
🌟 Совет: Если ты переходишь с Python на Swift, запомни главное отличие — в Swift строки это не просто массивы символов. Они работают с Unicode правильно, но требуют больше кода для простых операций с индексами.

Типичные ошибки и подводные камни

Ошибка 1: Забываешь, что методы возвращают новую строку

// ❌ Неправильно
var текст = "привет"
текст.uppercased() // Результат никуда не сохраняется!
print(текст) // Выведет "привет" — строка не изменилась

// ✅ Правильно
var текст2 = "привет"
текст2 = текст2.uppercased() // Сохраняем результат
print(текст2) // Выведет "ПРИВЕТ"

Ошибка 2: Путаешь count с length

// ❌ Неправильно — в Swift нет свойства length
let строка = "Привет"
// print(строка.length) // Ошибка компиляции!

// ✅ Правильно — используем count
print(строка.count) // 6

Ошибка 3: Пытаешься обратиться к символу по индексу как в Python

// ❌ Неправильно
let слово = "Swift"
// let первый = слово[0] // Ошибка! Так нельзя

// ✅ Правильно — используем индекс строки
let первыйИндекс = слово.startIndex
let первыйСимвол = слово[первыйИндекс]
print(первыйСимвол) // "S"

// Или используем свойство first
if let первый = слово.first {
    print(первый) // "S"
}

Ошибка 4: Забываешь про Optional при использовании first/last

// ❌ Неправильно — first возвращает Optional
let пустаяСтрока = ""
// let символ = пустаяСтрока.first // Тип — Character? (Optional)

// ✅ Правильно — используем if let
if let символ = пустаяСтрока.first {
    print("Первый символ: (символ)")
} else {
    print("Строка пустая")
}

Ошибка 5: Путаешь split с components

// split возвращает массив Substring, а не String
let текст = "яблоко,груша,банан"
let части = текст.split(separator: ",")
print(type(of: части[0])) // Substring, а не String

// Если нужны String, конвертируй:
let строки = части.map { String($0) }
print(type(of: строки[0])) // String

Лучшие практики и советы профессионалов

1. Используй многострочные литералы для длинного текста

// Плохо — длинная строка в одну линию
let длинныйТекст = "Это очень длинный текст, который не помещается на экране и его трудно читать, особенно когда нужно что-то исправить"

// Хорошо — используем многострочный литерал
let хорошийТекст = """
    Это очень длинный текст,
    который теперь легко читать,
    потому что он разбит на строки.
    """

2. Всегда проверяй строки на пустоту перед обработкой

// Плохо — может упасть с ошибкой
func первыйСимвол(_ текст: String) -> Character {
    return текст.first! // Force unwrap — опасно!
}

// Хорошо — безопасная проверка
func безопасныйПервыйСимвол(_ текст: String) -> Character? {
    guard !текст.isEmpty else {
        return nil
    }
    return текст.first
}

3. Используй raw strings для регулярных выражений

// Без raw strings — много экранирования
let сложныйШаблон = "\d{3}-\d{2}-\d{2}"

// С raw strings — чище и понятнее
let простойШаблон = #"d{3}-d{2}-d{2}"#

4. Группируй методы для читаемости

// Плохо — всё в одну строку
let результат = текст.lowercased().trimmingCharacters(in: .whitespaces).capitalized

// Хорошо — разбиваем на шаги
let очищенный = текст.trimmingCharacters(in: .whitespaces)
let вНижнемРегистре = очищенный.lowercased()
let красивый = вНижнемРегистре.capitalized

5. Используй extension для своих методов

// Создаём своё расширение для строк
extension String {
    // Метод, который проверяет, является ли строка email'ом
    func isValidEmail() -> Bool {
        return self.contains("@") && self.contains(".")
    }
    
    // Метод, который обрезает строку до определённой длины
    func truncated(to длина: Int) -> String {
        guard self.count > длина else { return self }
        return String(self.prefix(длина)) + "..."
    }
}

// Используем
let email = "test@example.com"
print(email.isValidEmail()) // true

let длинный = "Это очень длинный текст"
print(длинный.truncated(to: 10)) // "Это очень д..."

Вопросы для самопроверки

  1. Вопрос: Какой метод нужно использовать, чтобы сделать все буквы в строке заглавными?
    Ответ: uppercased(). Например: "привет".uppercased() вернёт "ПРИВЕТ".
  2. Вопрос: Чем отличается contains от hasPrefix?
    Ответ: contains проверяет, есть ли подстрока в любом месте строки. hasPrefix проверяет только начало строки.
  3. Вопрос: Почему в Swift нельзя написать строка[0] для получения первого символа?
    Ответ: Потому что Swift использует Unicode, и символы могут занимать разное количество байт. Нужно использовать String.Index или свойства first/last.
  4. Вопрос: Что вернёт " текст ".trimmingCharacters(in: .whitespaces)?
    Ответ: "текст" — удалит пробелы в начале и конце строки.
  5. Вопрос: Как разделить строку "яблоко,груша,банан" на массив строк?
    Ответ: Использовать split(separator: ","). Результат: ["яблоко", "груша", "банан"].
  6. Вопрос: В чём разница между count и length в Swift?
    Ответ: В Swift нет свойства length. Используется только count.
  7. Вопрос: Как заменить все вхождения слова "кот" на "пёс" в строке?
    Ответ: Использовать replacingOccurrences(of: "кот", with: "пёс").
  8. Вопрос: Что такое Optional и почему first возвращает Optional?
    Ответ: Optional — это тип, который может содержать значение или nil. first возвращает Optional, потому что строка может быть пустой.
  9. Вопрос: Как в Swift объединить массив строк в одну строку с разделителем?
    Ответ: Использовать joined(separator: "-"). Например: ["a", "b"].joined(separator: "-") вернёт "a-b".
  10. Вопрос: Почему в Swift строки называются иммутабельными?
    Ответ: Потому что методы строк не изменяют исходную строку, а возвращают новую. Это делает код безопаснее и предсказуемее.

Итог и что изучить дальше

Мы прошли большой путь! Теперь ты знаешь:

  • Что строки — это не просто текст, а мощные объекты с методами
  • Как изменять регистр, искать, заменять, разделять и объединять строки
  • Как работать с Unicode и эмодзи
  • Какие ошибки чаще всего допускают новички
  • Как писать чистый и безопасный код со строками

Это только начало. Строки в Swift — огромная тема. Вот что стоит изучить дальше:

  1. String.Index — научись работать с индексами строк. Это ключ к гибкой работе с текстом.
  2. Substring — узнай, чем отличается Substring от String и когда их использовать.
  3. Регулярные выражения (NSRegularExpression) — для сложного поиска и замены текста.
  4. Formatter (NumberFormatter, DateFormatter) — для красивого форматирования чисел и дат в строках.
  5. AttributedString — для работы с форматированным текстом (разные цвета, шрифты).
  6. Encoding (UTF-8, UTF-16) — как строки хранятся в памяти и конвертируются.
🎯 Главный совет: Не пытайся запомнить все методы сразу. Запомни основные (uppercased, contains, split, joined, replacingOccurrences) и всегда держи под рукой документацию Apple. Практика — лучший способ запомнить. Пиши маленькие программы, которые работают с текстом: анализатор паролей, форматировщик текста, простой поисковик.

Ты теперь не просто знаешь методы строк — ты понимаешь, как они работают изнутри. А это важнее, чем заучивание синтаксиса. Удачи в программировании! 🚀