0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【物語で学ぶ Swift Concurrency】Actor と Objective-C 連携方法

Last updated at Posted at 2025-02-18

Swift で登場した Actor 機能は、データ競合を避けるために設計された並行処理用の参照型です。ところが、この Actor を Objective-C と連携させたい場合、少し特殊なルールを理解しておく必要があります。本記事では、高校生アカリとカナメ先生の対話形式で、Actor と Objective-C をどう扱うのかを解説していきます。


【登場人物】

  • アカリ:高校生。プログラミング初心者だが Swift と Cocoa/Objective-C を学び始めたところ。
  • カナメ先生:高校の情報科教師。Swift の並行プログラミングやアクターについて詳しい。

アクターと Objective-C の相互運用について

アカリ:
先生、この前 Swift のアクターっていうのを勉強したんですけど、Objective-C とどうやって連携できるのか全然わかりません。学校の Mac で Cocoa アプリを作りたいなと思ってるんですが……。

カナメ先生:
なるほど、Swift のアクターと Objective-C の連携は少しややこしいかもしれないね。まず、アクターは並行処理でデータが競合しないように作られた特殊な“参照型”なんだ。アクターアイソレーション と呼ばれる仕組みで、アクター内部のプロパティやメソッドを安全に守ってくれるんだよ。

アカリ:
アクターアイソレーション……。つまりアクターの中では同時に複数の処理が走ったりしない、という感じでしょうか?

カナメ先生:
大まかにはそうだね。アクターは自分の状態を守るために“1度に1つのタスクしか実行しない”というルールで動いている。さて、これを Objective-C と連携させたいとき、@objc 属性を使うことができるんだ。


1. @objc とアクター

カナメ先生:
Swift の型に @objc を付けると Objective-C からもその型を見たり使ったりできるようになるよ。アクターも同じように、頭に @objc と書くことで、NSObjectProtocol に準拠しているとみなされるようになるんだ。

@objc actor MyActor {
    // ...
}

こう書くと、この MyActor は Objective-C から使えるようになる。

アカリ:
NSObjectProtocol にも自動で準拠するんですね。ただ、Swift のアクターが持っている「同期メソッド」「非同期メソッド」みたいなのはどうなるんですか?


2. 非同期メソッド (async) と 同期メソッド

カナメ先生:
実はこれがポイントなんだ。Objective-C では、アクターアイソレーション という概念を直接理解する仕組みがない。だから Swift のアクターで 同期メソッド を作っても、Objective-C 側から安全に呼び出す手段がないんだよ。結果的に、

  • 非同期メソッド (async)@objc で公開できる
  • 同期メソッド はアクターのアイソレーション内でしか使えないので、ふつうに @objc では公開できない

というルールが生まれる。

アカリ:
同期メソッドは、アクターの“保護された領域”内に閉じている、というイメージですね。

カナメ先生:
そうそう。だからアクターの同期メソッドをそのまま @objc にしようとすると、コンパイルエラーになってしまう。

例としては、こんなイメージだね:

@objc actor MyActor {
    @objc func synchronousMethod() {
        // error: part of actor's isolation domain
        // 同期メソッドはアクター内部だけで使うものなので
        // Objective-C に公開できない
    }
}

これはエラーになるんだ.


3. 非同期メソッド (async) の @objc 公開

アカリ:
じゃあ、非同期メソッドなら大丈夫なんですね?

カナメ先生:
そうだよ。非同期メソッドは、アクター内部の状態をアクセスする際に安全に扱えるし、Objective-C 側で呼び出すときは コールバック みたいな仕組みに自動的に変換されるんだ。こんな感じ:

@objc actor MyActor {
    @objc func asynchronousMethod() async {
        // ここはアクターアイソレーションで守られているけど、
        // Objective-C から呼べるようになる(内部的にはコールバック)
    }
}

この @objc func asynchronousMethod() async { ... } はコンパイルエラーにはならないんだ。Objective-C から呼び出す際には「完了ハンドラー」を使う形に自動変換してくれるイメージだね。


4. nonisolated を使うことで同期メソッドを公開

アカリ:
同期メソッドをまったく公開できないとなると不便そうです。何か方法はありますか?

カナメ先生:
あるよ。どうしても同期メソッドを Objective-C で呼びたい場合は、nonisolated 属性を使う手がある。これは「このメソッドはアクターの保護ドメインには属していない」という宣言になるんだ。つまり、アクターアイソレーションから外れるから Objective-C にも公開できる。

@objc actor MyActor {
    @objc nonisolated func nonIsolatedMethod() {
        // アクターアイソレーションを使わないコード
        // => Objective-C からも呼べる
    }
}

こう書くと同期メソッドでもコンパイルエラーにはならなくなる。ただし、その代わりにアクター内部の安全性(アイソレーション)を活かせなくなるので、使う側が自分でスレッドセーフか気をつける必要があるんだよ。

アカリ:
なるほど、nonisolated はアクターを通じた並行安全性の恩恵を受けられない分、Objective-C からアクセスできるようになるわけですね。


5. Objective-C との相互運用時の注意

アカリ:
結局、Objective-C はアクターアイソレーションがわからないからこそ制限がある、ということですか。

カナメ先生:
その通り。Objective-C から見ると、アクターが持つ「同期メソッドなのか」「非同期メソッドなのか」といった概念を直接は把握できない。だから、

  1. 非同期メソッド (async) はそのまま @objc として公開できる。
  2. 同期メソッド はアクターのアイソレーションと深く関係するので、通常は @objc として公開できない。
  3. もし同期メソッドを公開したいなら nonisolated を付けて「アクターアイソレーション外ですよ」と明示的にする必要がある。

という具合に整理されているんだ.


まとめ

  • アクターを @objc で宣言 することで、Objective-C からそのアクターを利用できるようになる。
  • 非同期メソッド (async)@objc として公開可能。
  • 同期メソッド はアクターアイソレーションの中でしか使えないため、通常 @objc として公開できない。
  • 同期メソッドを公開したい場合は @objc nonisolated を使う。ただし、その分アクターアイソレーションの恩恵は受けられなくなる。
  • Objective-C はアクターアイソレーションを理解しない ので、制限事項や安全性に注意が必要.

アカリ:
わかりました。つまり、アクターを Objective-C と連携させるときは「非同期メソッドだけは問題なく公開できる」「もし同期メソッドを公開したいなら nonisolated を付ける」という方針なんですね.

カナメ先生:
その通り! Swift のアクターと Objective-C の連携をするときは、このルールを意識しておけばだいたい困らないはずだよ。並行処理を使うアプリを作るときにぜひ活用してみてね.

アカリ:
ありがとうございます!頑張ってみます!

参考

Actor interoperability with Objective-C

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?