Что такое async/await? Что такое Task? Что такое actor?ios-51

1. Async/Await

Что это?

async/await — это современный подход к написанию асинхронного кода, который делает его похожим на синхронный, сохраняя все преимущества асинхронности.

Основные характеристики:

  • async - маркирует функцию как асинхронную
  • await - точка приостановки, где функция может быть прервана
  • Работает поверх Swift Concurrency (не путать с GCD)

Пример:

func fetchData() async throws -> Data {
    let url = URL(string: "https://api.example.com/data")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

Преимущества перед completion handlers:

  1. Прямой порядок выполнения
  2. Естественная обработка ошибок
  3. Нет проблем с callback hell

2. Task

Что это?

Task — это единица выполнения асинхронного кода, аналогичная понятию "задачи" в других языках.

Основные виды задач:

  1. Неструктурированные (Unstructured) - живут самостоятельно
  2. Структурированные (Structured) - связаны иерархией
  3. Детские (Child) - привязаны к родительской задаче

Пример создания:

Task {
    let data = try await fetchData()
    print("Received data: \(data)")
}

Особенности:

  • Имеют приоритеты (priority)
  • Поддерживают отмену (cancel())
  • Автоматически отслеживаются системой

3. Actor

Что это?

Actor — это тип, обеспечивающий безопасный доступ к изменяемому состоянию в многопоточной среде.

Основные принципы:

  1. Изоляция состояния (state isolation)
  2. Последовательный доступ к данным
  3. Автоматическая защита от гонок данных

Пример реализации:

actor BankAccount {
    private var balance: Double = 0

    func deposit(_ amount: Double) {
        balance += amount
    }

    func withdraw(_ amount: Double) -> Double {
        if balance >= amount {
            balance -= amount
            return amount
        }
        return 0
    }

    func currentBalance() -> Double {
        return balance
    }
}

Использование:

let account = BankAccount()

Task {
    await account.deposit(100)
    let current = await account.currentBalance()
    print("Current balance: \(current)")
}

Взаимодействие между концепциями

  1. Async функции выполняются в Task
  2. Actor обеспечивает безопасность данных при работе с async кодом
  3. Task может обращаться к actor только через await

Главные преимущества Swift Concurrency

  1. Безопасность:

    • Нет случайных гонок данных
    • Автоматическое управление памятью
    • Контролируемая отмена задач
  2. Производительность:

    • Оптимальное использование потоков
    • Минимальные накладные расходы
  3. Читаемость:

    • Линейный код вместо callback hell
    • Явное обозначение асинхронных операций

Практический пример

actor DataCache {
    private var storage: [String: Data] = [:]

    func getData(for key: String) async -> Data? {
        if let data = storage[key] {
            return data
        }

        // Асинхронная загрузка, если нет в кэше
        guard let data = try? await downloadData(from: key) else {
            return nil
        }

        storage[key] = data
        return data
    }

    private func downloadData(from urlString: String) async throws -> Data {
        let url = URL(string: urlString)!
        let (data, _) = try await URLSession.shared.data(from: url)
        return data
    }
}

// Использование
Task {
    let cache = DataCache()
    if let data = await cache.getData(for: "https://example.com/image.jpg") {
        print("Got data: \(data.count) bytes")
    }
}

Резюмируем:

  • Async/await — парадигма написания асинхронного кода
  • Task — единица выполнения асинхронной работы
  • Actor — механизм безопасного доступа к общему состоянию

Вместе они образуют мощную систему конкурентности в Swift, которая сочетает безопасность, производительность и удобство разработки.