Введение: Почему разбиение строки — база, которую обязан знать каждый Swift-разработчик
Представьте ситуацию: вы парсите CSV-файл, обрабатываете пользовательский ввод из текстового поля или разбираете JSON-подобную строку. Что вы делаете? Правильно — разбиваете строку на массив. Вопрос "Split a String into an array in Swift?" на Stack Overflow набрал более 20 000 просмотров и стал одним из самых популярных среди начинающих iOS-разработчиков. Почему? Потому что без этого навыка невозможно написать ни один серьёзный проект на Swift.
В этой статье мы разберём все возможные способы разбить строку на массив в Swift: от классического components(separatedBy:) до современного split(separator:) и хитрых приёмов с регулярными выражениями. Вы узнаете, какой метод выбрать в зависимости от задачи, и получите готовые примеры кода, которые можно сразу вставить в свой Xcode-проект.
1. Классический метод: components(separatedBy:)
Этот метод пришёл к нам из Objective-C и до сих пор активно используется. Он прост, понятен и работает как швейцарские часы. components(separatedBy:) возвращает массив строк [String], разделённых указанным разделителем.
import Foundation
let text = "яблоко,банан,апельсин,киви"
let fruits = text.components(separatedBy: ",")
print(fruits) // ["яблоко", "банан", "апельсин", "киви"]
Важные нюансы метода components(separatedBy:):
- Разделитель — строка. Можно передать любой
String, даже из нескольких символов:"::"," - ". - Пустые элементы сохраняются. Если между разделителями ничего нет, в массиве появится пустая строка.
- Требуется import Foundation. Без импорта метод недоступен.
let data = "a,,b,c"
let parts = data.components(separatedBy: ",")
print(parts) // ["a", "", "b", "c"]
Этот метод идеально подходит, когда вам нужно просто и быстро разбить строку на массив в Swift без лишних заморочек. Но помните: он не удаляет пустые подстроки автоматически.
2. Современный метод: split(separator:maxSplits:omittingEmptySubsequences:)
Начиная с Swift 2.0, у нас есть нативный метод split(). Он более гибкий и «свифтовый». В отличие от components, split возвращает массив Substring, а не String. Это сделано для оптимизации производительности — подстроки ссылаются на память исходной строки.
let sentence = "Быстрая бурая лиса прыгает через ленивую собаку"
let words = sentence.split(separator: " ")
print(words) // ["Быстрая", "бурая", "лиса", "прыгает", "через", "ленивую", "собаку"]
Параметры метода split:
separator— символ-разделитель (Character).maxSplits— максимальное количество разбиений (по умолчаниюInt.max).omittingEmptySubsequences— нужно ли удалять пустые подстроки (по умолчаниюtrue).
let csvLine = "1,2,,4,5"
let withEmpties = csvLine.split(separator: ",", omittingEmptySubsequences: false)
print(withEmpties) // ["1", "2", "", "4", "5"]
let withoutEmpties = csvLine.split(separator: ",", omittingEmptySubsequences: true)
print(withoutEmpties) // ["1", "2", "4", "5"]
Если вам нужно разбить строку на массив Substring в Swift и вы хотите контролировать пустые элементы — выбирайте split. А чтобы получить [String], просто добавьте .map(String.init).
let result: [String] = "a,b,c".split(separator: ",").map(String.init)
print(result) // ["a", "b", "c"]
3. Разбиение с несколькими разделителями
Что делать, если строка содержит разные разделители? Например: "яблоко;банан,апельсин|киви". Тут вам поможет components(separatedBy: CharacterSet) или split(whereSeparator:).
Используем CharacterSet:
import Foundation
let messy = "яблоко;банан,апельсин|киви"
let separators = CharacterSet(charactersIn: ";,|")
let items = messy.components(separatedBy: separators)
print(items) // ["яблоко", "банан", "апельсин", "киви"]
Используем замыкание в split:
let items2 = messy.split { $0 == ";" || $0 == "," || $0 == "|" }
print(items2) // ["яблоко", "банан", "апельсин", "киви"]
Второй способ более «свифтовый» и читаемый. Вы просто передаёте замыкание, которое возвращает true для символов-разделителей. Это особенно удобно, когда логика разделения сложнее простого перечисления.
4. Разбиение по регулярному выражению
Иногда разделитель — это не просто символ, а целый паттерн. Например, нужно разбить строку по всем пробельным символам (пробелы, табуляции, переносы строк) или по числам. Тут на помощь приходит NSRegularExpression.
import Foundation
let text = "Код: 123, статус: активен, дата: 2024-01-15"
let pattern = "\\d+"
let regex = try! NSRegularExpression(pattern: pattern)
let range = NSRange(text.startIndex..., in: text)
let matches = regex.matches(in: text, range: range)
let parts = matches.map { match -> String in
let range = Range(match.range, in: text)!
return String(text[range])
}
print(parts) // ["123", "2024", "01", "15"]
Для простых случаев лучше использовать split или components, но когда паттерн сложный — регулярные выражения незаменимы. Только не забывайте про try! — в продакшене лучше обрабатывать ошибки.
5. Частые ошибки и как их избежать
Ошибка 1: Забыли импортировать Foundation
Метод components(separatedBy:) не скомпилируется без import Foundation. split же доступен без импорта, но если вы работаете с CharacterSet — Foundation снова нужен.