【Swift Concurrency】@MainActorと@globalActorの違いと使い方!

この記事からわかること
- Swift Concurrencyとは?
- @MainActorと@globalActorの違いと使い方
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- macOS:Sonoma 14.6.1
Swift Concurrency
で導入されたActor
は異なるスレッド間からの同時アクセスを制御しデータの競合が発生して不整合が起きないようにするためののものでした。
複数のスレッドからのアクセスを制御できるActor
を学んでいくと@MainActor
属性と@globalActor
属性が出てきます。今回はこれらについてまとめていきます。
Global Actor(グローバルアクター)
「Global Actor(グローバルアクター)」とは特定のスレッドで実行されることを保証することができるカスタム可能なActorで@globalActor
属性を使用することで独自のGlobal Actorを定義することができます。
例えば上記のように定義したBackgroundActor
は関数やクラスなどの前に付与することで実行するスレッドをBackgroundActorのスレッドに強制させることができます。
@MainActor属性
@MainActor
属性はあらかじめ定義されているGlobal Actorです。名前の通り@MainActor
属性を付与した関数などをメインスレッドでの実行を強制することができるGlobal Actorです。Swiftの世界でも実際に使用されていてSwift UIではViewプロトコルのbody
プロパティやUIKitではUIViewController
などに付与されています。
使い方
@MainActor
属性は関数やクラスに対して付与して使用します。例えばグローバル関数として定義されたshowPopUpWindow
があるとします。このメソッドはUIを更新するような処理の場合、メインスレッドからの操作が必要不可欠になります。このような場合に@MainActor
属性を付与するとメインスレッドで実行されることが保証されるようになります。
@MainActor
属性を付与した関数を呼び出す場合はメインスレッドから非同期的に呼び出す必要があり、非同期的に呼び出さない場合などは以下のエラーを吐きます。
- Call to main actor-isolated global function 'showPopUpWindow()' in a synchronous nonisolated context
そのためDispatchQueue.main.async
やTask { await }
を活用して明示的に非同期かつメインスレッドで呼び出すようにします。
呼び出す関数に@MainActor
が付与されていればその中では同期的に呼び出すことができますが結果その関数を呼び出すときには同じになります。
クラスに付与する
@MainActor
は関数だけでなくクラス自体にも付与することができます。@MainActor
を付与したクラスはインスタンス化する際もメインスレッドから非同期的に呼び出す必要があります。
nonisolated
キーワードを付与することで特定のメソッドだけisolate
(隔離)しないようにすることもできます。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。