Ответ
Swift предлагает несколько уровней абстракции для работы с многопоточностью, от низкоуровневых системных API до современных языковых конструкций.
1. Grand Central Dispatch (GCD)
Низкоуровневый C-API, управляющий очередями задач (DispatchQueue).
- Главная очередь (Main Queue):
DispatchQueue.main— для обновления UI. - Глобальные очереди: Фоновые очереди с приоритетами качества обслуживания (QoS).
DispatchQueue.global(qos: .userInitiated).async { // Тяжёлая задача let result = processData() // Возврат в главный поток для обновления UI DispatchQueue.main.async { updateUI(with: result) } } - Пользовательские очереди: Можно создавать серийные (
.serial) или конкурентные (.concurrent) очереди.
2. OperationQueue
Высокоуровневая Objective-C-абстракция над GCD, построенная на классах Operation. Позволяет:
- Устанавливать зависимости между задачами.
- Отменять задачи.
- Ограничивать количество параллельных операций (
maxConcurrentOperationCount).
3. Swift Concurrency (async/await) Современная модель, представленная в Swift 5.5. Упрощает написание асинхронного и параллельного кода.
- Асинхронные функции: Помечаются ключевым словом
async.func fetchData() async throws -> Data { let (data, _) = try await URLSession.shared.data(from: url) return data } - Задачи (Task): Являются единицей выполнения.
Task { // Автоматически выполняется в фоновом потоке let data = await fetchData() // `await MainActor.run` гарантирует выполнение в главном потоке await MainActor.run { self.label.text = String(data: data, encoding: .utf8) } } - Акторы (Actors): Предоставляют механизм изоляции состояния для безопасного доступа из разных потоков.
Выбор инструмента:
- Swift Concurrency — предпочтительный выбор для нового кода.
- OperationQueue — для сложных зависимостей и отменяемых задач.
- GCD — для простых фоновых задач или низкоуровневого контроля.
Ответ 18+ 🔞
Слушай, а ведь Swift, этот хитрожопый язык, на самом деле даёт нам целую палитру способов устроить многопоточный бардак. От таких низкоуровневых штук, что прям в ядро системы лезут, до этих ваших модных async/await, от которых у старых разработчиков волосы дыбом встают. Давай разбираться, пока не съехала крыша.
1. Grand Central Dispatch (GCD) — старый, добрый, местами злой.
Это как бы такой фундаментальный C-API, который вертит очередями задач, будто шаманы бубнами. Основа основ — DispatchQueue.
- Главная очередь (Main Queue):
DispatchQueue.main. Это святое, блядь. Сюда только обновлять интерфейс. Кто сюда лезет с тяжёлой задачей — тот полупидор. - Глобальные очереди: Фоновые рабочие лошадки. У них даже приоритеты есть, QoS называется.
.userInitiated— «срочно, ёпта»,.utility— «сделай как-нибудь потом».// Кидаем тяжёлую хуйню в фон DispatchQueue.global(qos: .userInitiated).async { let result = self.processData() // Тут всё грузится и тормозит // А теперь ВОЗВРАЩАЕМСЯ НА ГЛАВНУЮ, сука, не забываем! DispatchQueue.main.async { self.updateUI(with: result) // И только тут тыкаем в интерфейс } } - Свои очереди: Можешь наклепать серийных (
.serial, одна задача за другой) или конкурентных (.concurrent, несколько сразу). Как тебе угодно, главное — не перепутай, а то получишь гонку данных, и пиши пропало.
2. OperationQueue — хитрая надстройка над GCD.
Высокоуровневая абстракция из мира Objective-C. Работает с объектами Operation. Её фишка в том, что она не просто выполняет, а управляет задачами. Можно сказать одной операции: «Э, дружок, не начинай, пока вот эта вот не закончит» (зависимости). Или взять и отменить всё к хуям собачьим. Или ограничить, сколько операций могут городить огород одновременно (maxConcurrentOperationCount). Удобно для сложных пасьянсов.
3. Swift Concurrency (async/await) — новое, модное, молодёжное. Появилось в Swift 5.5 и всех поначалу оху... то есть, сильно удивило. Суть — писать асинхронный код почти как обычный, линейный.
- Асинхронные функции: Помечаешь
asyncи спишь спокойно.func fetchData() async throws -> Data { // Смотри, какая красота! Никаких completionHandler-ов, одна строка! let (data, _) = try await URLSession.shared.data(from: url) return data } - Задачи (Task): Это такая обёртка, внутри которой этот волшебный
async-код и выполняется.Task { // Всё, что после `await`, автоматически уедет в фон, если надо let data = try? await fetchData() // А чтобы ткнуть в UI, надо явно сказать: «Эй, я на главный поток хочу!» await MainActor.run { self.label.text = String(data: data, encoding: .utf8) } } - Акторы (Actors): Это вообще песня. Такая сущность, которая защищает свои внутренние данные от пиздеца, когда к ним ломятся со всех потоков сразу. Самый надёжный буфер от твоей криворукости.
Так что же выбрать, ёпта?
- Swift Concurrency — это сейчас главная дорога. Для всего нового кода — бери это. Прям вот в рот меня чих-пых, как же удобно!
- OperationQueue — если у тебя там задачи, как в матрёшке, одна из другой вылезает, или тебе жизненно важно иметь кнопку «Отмена».
- GCD — для простых одноразовых выстрелов в фон («сохрани файлик») или если ты любитель поковыряться в низкоуровневых кишках. Старая, добрая, проверенная временем кувалда.