Что такое протокол Sendable в Swift?

«Что такое протокол Sendable в Swift?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Sendable — это маркерный протокол (marker protocol), введенный в Swift 5.5. Он указывает, что значения данного типа можно безопасно передавать между разными областями конкурентности (concurrency domains), например, между акторами или потоками.

Цель: Предотвращение гонок данных (data races) в конкурентном коде, гарантируя, что передаваемые данные либо неизменяемы, либо должным образом синхронизированы.

Какие типы автоматически соответствуют Sendable?

  • Значимые типы (Value types) с Sendable-свойствами: Int, String, Bool, а также struct и enum.
  • Акторы (Actors): По своей природе изолируют своё состояние.
  • Функции: Только @Sendable-замыкания.

Пример объявления:

// Структура автоматически соответствует Sendable, так как все её свойства — Sendable типы.
struct UserProfile: Sendable {
    let userId: Int
    let username: String
}

// Класс должен быть явно помечен как `final` и иметь только неизменяемые (`let`) Sendable-свойства.
final class ImmutableConfig: Sendable {
    let apiEndpoint: String
    let timeout: Int
    init(apiEndpoint: String, timeout: Int) {
        self.apiEndpoint = apiEndpoint
        self.timeout = timeout
    }
}

Где используется? Компилятор требует соответствие Sendable при:

  • Передаче данных в Task или async let.
  • Использовании типа в качестве аргумента @Sendable-замыкания.
  • Передаче данных между акторами.

Важно: Классы, содержащие изменяемое состояние или ссылки на не-Sendable типы, не могут быть безопасными для передачи. Компилятор выдаст ошибку на этапе компиляции.