Skip to content

global actorへの隔離

global actor は、アプリ全体で共有される一つのactorです。前のページのactorの例のように、actorはインスタンスごとに独立したisolation domainを持つのに対してglobal actorはアプリケーション全体で一つのisolation domainを持ちます。

では、global actorで状態、関数を隔離する例を、最も有名なglobal actorであるMainActorを例に解説します。 MainActorは最初からシステムが用意しているglobal actorであり、全ての処理がメインスレッド上で実行されるという特徴があります。

global actor への隔離は、クラス、関数、変数の宣言にアノテーションを書いて行います。MainActor なら @MainActor です。

@MainActor
class GameLibraryViewController: UIViewController {
func updateUI() {
// 画面に出ている表示を更新する
}
}
@MainActor
var libraryTitle = "ゲーム"
@MainActor
func reloadLibrary() {
libraryTitle = "更新したゲーム"
}

クラスに@MainActorをつけると、そのクラスのプロパティ、メソッドもMainActorのisolation domainに隔離されます。 関数や、変数には、それぞれの宣言に直前に、クラスと同様に@MainActorをつけることでisolation domainに隔離されます。libraryTitle と reloadLibrary() はクラスの外にありますが、GameLibraryViewController と同じisolation domainに隔離されます。

MainActorは最初から用意されているglobal actorですが、自身でglobal actorを定義することもできます。 以下の例の通り、@globalActorアノテーションをつけることで、アプリ全体で共有されるglobal actorを定義することができます。

struct Videogame {
var title: String
}
@globalActor
struct MediaActor {
actor ActorType { }
static let shared = ActorType()
}
@MediaActor
var videogames: [Videogame] = []
@MediaActor
func addGame(_ game: Videogame) {
videogames.append(game)
}

videogames と addGame は、どちらも MediaActor.shared に隔離されます。 そして、MediaActor の外から addGame を呼ぶ時には、await が必要です。

func register(_ game: Videogame) async {
await addGame(game)
}