0Pricing
Swift Academy · Урок

Протокол Sendable

Помечайте типы как безопасные для передачи между доменами конкурентного выполнения.

«Протокол Sendable» — бесплатный урок Swift Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.

Что означает передаваемый тип

Sendable — это маркерный протокол. Тип, соответствующий ему, обещает быть безопасным для совместного использования в разных областях конкурентности без возникновения гонок данных.

У него нет методов; это проверяемая компилятором гарантия безопасности при работе с потоками.

protocol Sendable {}

Типы-значения часто являются передаваемыми

Структуры и перечисления, все хранимые свойства которых имеют тип Sendable, могут соответствовать этому протоколу автоматически.

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

struct User: Sendable {
    let id: Int
    let name: String
}

Неявное соответствие

Многие типы-значения получают соответствие Sendable неявно: непубличные неизменяемые структуры и перечисления с элементами Sendable, кортежи типов Sendable и метатипы.

Для внутренних типов-значений часто вообще не нужно писать : Sendable.

enum Direction { case north, south, east, west }
// Implicitly Sendable: no associated non-Sendable data

Когда структура NOT является передаваемой

Если структура содержит хранимое свойство, не являющееся Sendable, она не является передаваемой.

Здесь ссылка на класс делает общее изменяемое состояние доступным, поэтому компилятор отказывается автоматически добавлять соответствие.

final class Box { var value = 0 }
struct Wrapper { // not Sendable
    let box: Box // class with mutable state
}

Классы и передаваемость

Классы являются ссылочными типами, поэтому копии используют один и тот же экземпляр. Класс является Sendable только в том случае, если он финальный, а все его хранимые свойства неизменяемы и являются Sendable.

final class ImmutablePoint: Sendable {
    let x: Double
    let y: Double
    init(x: Double, y: Double) { self.x = x; self.y = y }
}

@unchecked Передаваемость

Иногда Вы знаете, что класс потокобезопасен (он защищает состояние с помощью lock), но компилятор не может это доказать. Используйте @unchecked Sendable, чтобы вручную подтвердить безопасность.

Это обходной путь: Вы берёте на себя ответственность за корректность.

import Foundation
final class Cache: @unchecked Sendable {
    private let lock = NSLock()
    private var storage: [String: Int] = [:]
    func set(_ k: String, _ v: Int) {
        lock.lock(); defer { lock.unlock() }
        storage[k] = v
    }
}

Замыкания @Sendable

Замыкания также можно пометить как @Sendable. Такое замыкание можно передавать через границы конкурентного выполнения, поэтому компилятор проверяет, что оно захватывает только передаваемые значения.

func run(_ work: @Sendable () -> Void) {
    work()
}
let name = "Ada" // immutable, Sendable
run { print(name) }

Захват изменяемого состояния отклоняется

Замыкание @Sendable не может захватывать изменяемую переменную, поскольку две задачи могут изменять её одновременно.

Компилятор сообщает об ошибке захвата ниже.

var counter = 0
// Error: @Sendable closure captures mutable var
// run { counter += 1 }

Передаваемость в асинхронных API

Точки входа в конкурентное выполнение требуют Sendable. Замыкания Task являются @Sendable, а значения, передаваемые другим акторам, должны быть передаваемыми.

Так система типов не позволяет небезопасным для потоков данным просачиваться между задачами.

func process(_ user: User) async {
    Task {
        // user is Sendable, safe to capture
        print(user.name)
    }
}

Ограничения передаваемости в обобщениях

В обобщениях можно потребовать передаваемость. Функция, создающая задачи с использованием своего аргумента, должна ограничивать этот аргумент типом Sendable.

func dispatch<T: Sendable>(_ value: T) {
    Task { print(value) }
}

Передаваемость и актор

Sendable отвечает на вопрос «безопасно ли передавать это значение?», а actor — на вопрос «как защитить изменяемое состояние?»

Они сочетаются: акторы неявно являются передаваемыми, поскольку доступ к их состоянию сериализуется.

actor Logger { } // actors are implicitly Sendable

Быстрая проверка: передаваемость

Проверьте своё понимание соответствия передаваемости.

Итоги: протокол передаваемости

Sendable помечает типы, безопасные для передачи через границы конкурентного выполнения. Неизменяемые типы-значения получают соответствие автоматически; финальные неизменяемые классы могут ему соответствовать; потокобезопасные классы используют @unchecked Sendable.

Замыкания @Sendable могут захватывать только передаваемые значения, а асинхронные API требуют Sendable, чтобы предотвращать небезопасное совместное использование. Вместе с акторами Sendable образует типовую основу безопасности Swift в отношении гонок данных.

Часто задаваемые вопросы

Урок «Протокол Sendable» бесплатный?

Да — полный текст урока «Протокол Sendable» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.

Чему я научусь в уроке «Протокол Sendable»?

Помечайте типы как безопасные для передачи между доменами конкурентного выполнения. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Swift Academy?

Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Протокол Sendable»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Swift Academy?

Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Проблема гонки данных
  2. Протокол Sendable
  3. Изоляция акторов и nonisolated
  4. Переход на строгую конкурентность
← Назад к Swift Academy