Swiftのactorで状態を守るときに見ること
Swift Concurrencyで共有状態を扱うとき、actor が出てきます。
複数のTaskから同じ値を読み書きすると、順番や競合が分かりづらくなります。actorは、その状態へのアクセスを直列化して守るための仕組みです。
公式ドキュメントでも、actorは可変状態への同時アクセスを安全にするものとして説明されています。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Actors
actorの基本
actor Counter {
private var value = 0
func increment() {
value += 1
}
func current() -> Int {
value
}
}
actorの外からメソッドを呼ぶときは await が必要です。
let counter = Counter()
await counter.increment()
let value = await counter.current()
actorの内部状態にアクセスするには、そのactorの実行コンテキストに入る必要があります。
なぜawaitが必要なのか
actorは内部の状態を守るため、外からの呼び出しを順番に処理します。
そのため、呼び出し側から見ると待ちが発生する可能性があります。
let value = await counter.current()
await は「ここで一時停止する可能性がある」という印です。
MainActorとの違い
MainActor は、メインスレッド上で実行したい処理に使われます。
@MainActor
final class ViewModel: ObservableObject {
@Published var count = 0
}
UI更新はMainActorに寄せることが多いです。
一方で、通常のactorは独自の分離領域を持つ共有状態に使います。
| 使うもの | 場面 |
|---|---|
actor |
独自の共有状態を守る |
@MainActor |
UI更新やメインスレッド上の状態 |
使いどころ
actorは、次のような状態に向いています。
- 複数Taskから更新されるキャッシュ
- 同時アクセスされるカウンタ
- バックグラウンド処理の進捗管理
- 接続状態やセッション状態
単純なローカル変数までactorにする必要はありません。
まとめ
actorは、Swift Concurrencyで共有状態を守るために使います。
- actor内部の状態は外から直接触れない
- actorのメソッド呼び出しには
awaitが必要 - UI更新は
@MainActor - 独自の共有状態には通常の
actor
Task が増えて状態が散らばってきたら、actorに寄せられるかを見ると整理しやすいです。


