4. Sendable
Изучение данного блока предполагает предварительное знание синтаксиса языка Swift. Для успешного освоения этого материала, необходимо иметь базовое понимание синтаксиса языка Swift. Это включает в себя знание основных структур данных, операторов, циклов, функций, абстракций и других ключевых элементов языка. Без этих фундаментальных знаний будет сложно понять более сложные концепции и примеры, которые будут рассматриваться в данном блоке.
Работая с async/await мы постоянно переключаемся между состояниями, в этот момент функции приостанавливаются и продолжают своё исполнение. В такой работе стоит подумать о данных, потому что резко увеличивается вероятность возникновения гонки данных.
Гонка данных (Напоминание)¶
Гонки данных происходят, когда к одной и той же памяти обращаются из нескольких потоков без синхронизации, и по крайней мере один доступ является записью**. Гонки данных могут привести к нескольким проблемам:
- Непредсказуемое поведение
- Повреждение памяти
- Ненадежные тесты
- Странные сбои
STRICT CONCURRENCY¶
Понимая, что проблема Data Race может усугубиться с внедрением async/await - команда swift внедрила различные проверки на этапе компиляции кода, которые подсказывают разработчикам о возможной гонке данных. Если вы начали внедрять async/await и не видите никаких предупреждений, то вероятнее всего у вас стоит низкий уровень проверки компилятора. Чтобы включить полную проверку компилятора - необходимо зайти в Build Settings -> SWIFT_STRICT_CONCURRENCY = complete

Sendable¶
Если обратиться к официальной документации swift, то
Sendable - это протокол, который говорит компилятору о том, что значения могут безопасно передаваться между асинхронными функциями, не вызывая при это гонки данных.
Sendable + Struct, Enum¶
Чтобы структура удовлетворяла протоколу Sendable, необходимо, чтобы все проперти были Sendable. Если вы понимаете, что в будущем ваша структура будет изменяться и может появиться новое изменяемое проперти внутри и при этом вам необходимо, чтобы структура была Sendable, то лучше сразу её пометить Sendable
Есть также неявное соответствие протоколу Sendable.
@frozenструктуры и енумы- Структуры и перечисления, которые не являются public и не помечены как
@usableFromInline.
Sendable + Class¶
Для того, чтобы класс удовлетворял протоколу Sendable, необходимо, чтобы:
- Он был помечен
final - Содержать только stored properties, которые не изменяемы и также помечены
Sendable - Не должен иметь родительского класса и не должен наследоваться от
NSObject
Если класс помечен как @MainActor - то он Sendable, потому что @MainActorобеспечивает внутри безопасный доступ к переменным класса и такие классы уже внутри себя могут иметь любые проперти.
Sendable + Actors¶
Все типы экторов - удовлетворяют протоколу Sendable. (по определению actor)
Sendable + Функции, кложуры¶
Мы части пишем функции, которые используют дженерики или в параметрах используются протоколы, для того, чтобы не помечать все типы Sendable, можно просто использовать Sendable в функциях, тем самым показывая другим разработчикам, что мы ожидаем в этой функции или кложуре Sendable тип.
let sendableClosure = { @Sendable (number: Int) -> String in
if number > 12 {
return "More than a dozen."
} else {
return "Less than a dozen"
}
}
Sendable + Tuples¶
Кортеж является Sendable, только в том случае если все его элементы являются Sendable
Sendable + Примитивы¶
Все метатипы такие как Int, Bool и другие по умолчанию Sendable.
Unchecked Sendable¶
Отключает проверки компилятора в данном классе/структуре. Написав unchecked sendable вы полностью берёте ответственность на себя, говоря компилятору:
"Я уверен, что всё, что находится внутри - готово к работе с асинхронным контекстом и проблем с гонками данных не возникнет"
Команда swift не рекомендует использовать часто @unchecked Sendable, чтобы случайно не отключить нужные проверки.
Итог¶
Хочется сказать, что в первую очередь Sendable нужен именно нам (разработчикам), чтобы мы могли выстраивать правильный код, который при расширении в дальнейшем не вызывал бы проблем. Поэтому я настоятельно рекомендую обдумывать все ворнинги компилятора и быть осторожными, когда вы пишите @unchecked Sendable