Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 Контент вільний від AI. Цей пост на 100% написаний людиною, як і все на моєму блозі. Насолоджуйтесь!

21.09.2024

Оновлення до Swift 6 та його моделі рівночасності

Оновлював свої застосунки на Swift до свіжого Swift 6. Це вимагає дотримання моделі рівночасності. Досвід був цікавий. Простий застосунок майже не потребує змін. Але деякі функції вимагають переписування, навіть якщо в моєму коді немає акторів.

Мій застосунок з HealthKit був найбільш неприємним. HealthKit отримав новий набір API з асинхронністю, що чудово. От тільки старі API викликають непрозору помилку в асемблерному коді та ще й без стека. Суть помилки, як я зрештою зрозумів — що колбек був викликаний не в очікуваній “черзі”. А саме, в черзі @MainActor, а не в фоновій. Довелось переписати весь код з колбеками на API з async, причому розшукувати його вручну. Результатом я задоволений, але досвід розробки максимально вражий.

Ще в мене є застосунок для перегляду світлин, в ньому є фонове завантаження. Тут модель акторів дійсно корисна. Вирішив для себе, що найзручніше це зробити глобальний актор для менеджера завантажень, та призначити йому всі класи, що стосуються завантажень. Тоді внутрішні операції в цій області відбуваються синхронно, а на стику з інтерфейсом, тобто @MainActor, зʼявляється асинхронність.

Взагалі ментальна модель безпеки Swift така, що кожна змінна належить одному з акторів. Тому ми думаємо не про послідовність та синхронізацію операцій, а про власність над даними. Та цікаво, що власність не залежить від розташування змінних, наприклад, посередині нашого актора може бути атрибут чи функція з власністю @MainActor.

Та другий аспект — це типи Sendable - які дозволено передавати з актора в актора, або захопити в замиканнях з іншого актору. З цим доводиться помізкувати. Наприклад, мав проблеми з AVAssetWriterInput. Там API з колбеком “дай мені ще кадрів”. Цей колбек важко уявити без зовнішнього стану. Але ось проблема: якщо я викликаю метод всередині актору, то колбек все одно буде викликаний в іншій черзі — та в ньому не дозволено змінювати захоплені змінні. Знайшов цікаве рішення, де будь-яку змінну можна зробити Sendable, якщо додати до неї обгортку та замок.

Принаймні це оновлення є хорошою вправою та новим для мене способом думати про безпеку рівночасних операцій.