Использование MainActor в Swift для выполнения задач в главном потоке
MainActor — это новый атрибут, представленный в Swift 5.5 в качестве глобального актора, который предоставляет исполнитель (executor), выполняющий свои задачи в главном потоке. При создании приложений крайне важно выполнять операции, связанные с обновлением пользовательского интерфейса (UI), в главном потоке, что может быть проблематично при работе с несколькими фоновыми потоками. Использование атрибута @MainActor поможет убедиться, что ваш UI всегда обновляется в главном потоке.
Если вы новичок в теме акторов (Actors) в Swift, рекомендую ознакомиться с моей статьёй «Actors in Swift: how to use and prevent data races». Глобальные акторы работают похожим образом, поэтому в этой статье мы не будем углубляться в то, как устроены акторы в целом.
Что такое MainActor?
MainActor — это глобально уникальный актор, который выполняет свои задачи в главном потоке. Вы можете использовать его для свойств, методов, экземпляров и замыканий, чтобы гарантировать выполнение задач именно в главном потоке. Предложение SE-0316 Global Actors представило main actor в качестве примера глобального актора, который наследуется от протокола GlobalActor.
Понимание глобальных акторов (Global Actors)
Прежде чем мы перейдём к тому, как использовать MainActor в вашем коде, важно понять концепцию глобальных акторов. Их можно рассматривать как синглтоны: существует ровно один такой экземпляр. Мы можем определить глобальный актор следующим образом:
@globalActor
actor SwiftLeeActor {
static let shared = SwiftLeeActor()
}
Свойство shared — это требование протокола GlobalActor, гарантирующее наличие глобально уникального экземпляра актера. После определения вы можете использовать данный глобальный актор во всём проекте точно так же, как и любой другой актор:
@SwiftLeeActor
final class SwiftLeeFetcher {
// ..
}
Везде, где вы используете атрибут глобального актора, синхронизация будет происходить через его общий экземпляр (shared), чтобы обеспечить взаимное исключение при доступе к объявлениям (например, свойствам и методам). Результат аналогичен работе акторов в целом, как описано в статье «Actors in Swift: how to use and prevent data races».