Objective-CなどiOS関連の技術メモ。知識はここに投げ捨てて忘れる。

NSRunLoop

最終更新日 2013年07月21日 12:42

NSRunLoopの大雑把な概念について解説する。

スレッドのおさらい

NSRunLoopを理解するにあたって、まずスレッドのことをおさらいしておこう。新しいスレッドを作るときは、そのスレッド上で実行するメソッドを指定する。仮にそのメソッドのシグネチャをaMethodとすると、コードは次のようになる。

スレッドが実行する処理はメソッド呼出の積み重ねになる。aMethodの内部でbMethod呼び出しが行われ、さらにその中でcMethodが呼び出される、という具合に。そして、cMethodが終了すると戻り値がbMethodに返り、同様にbMethodは戻り値をaMethodに返し、最後にaMethodがreturnすると、そのスレッドは終了する。

performSelectorメソッド

ここでperformSelector:onThread:withObject:waitUntilDone:メソッドについて考えてみたい。このメソッドは指定したスレッド上で任意のメソッドを実行するために使う。NSObjectに定義されており、どのObjective-Cオブジェクトに対しても呼び出すことができる。

「指定したスレッド上で」実行というが、さきほどおさらいしたスレッドの処理フローの中に、スレッド外部からいきなり別のメソッドを実行しろと言われて実行できる余地があっただろうか。スレッドが実行する処理はメソッド呼び出しが積み重なった一本の線のようなもの。普通のスレッドは、performSelectorでメソッドの実行を依頼されても、対応などできないのである。

次のような例を考えてみよう。countDownメソッドは3秒のカウントダウンを行う。これを新規作成したスレッドで実行した上で、そのスレッドに対してperformSelectorでhelloメソッドの実行を指示する。結果はどうなるだろうか。

結果は、カウントダウンを行ったあと、performSelectorの実行で “target thread exited while waiting for the perform” というエラーとなる。「helloメソッドの実行をまってたら、スレッドが終了してしまったでござる」ということだ。スレッドはcountDownメソッドを実行し終わると、performSelectorによる要求に応えず、そのまま終了してしまったのである。

そこでNSRunLoop

そこで出てくるのがNSRunLoop。これは要するに、外部からスレッドに処理を依頼するperformSelector系のメソッドに対応するための仕組みと考えればわかりやすい。外部からアクセスするための窓口(ポート)を開き、ループしながら、依頼されたメソッドを順に実行していく、その処理自体を表しているクラスである。

先ほどのカウントダウンの例ででてきたcountDownメソッドの最後に、次の一文を加えて再実行してみると、今度はhelloメソッドが正しく実行される。

ひとつのスレッドが同時に2つのループをまわせるわけがないので、NSRunLoopオブジェクトはひとつのスレッドにつき、あってもひとつだけである。[NSRunLoop currentRunLoop]がその唯一のオブジェクトを取得するメソッドなわけだが、そのスレッドに紐付いているNSRunLoopオブジェクトがまだ作成されていなかった場合は新たに作成される、ということも知っておくといいだろう。

そしてrunMode:beforeDateメソッドでループを回す。メソッド名からは少しわかりにくい。runWithModeという名前にしてくれたほうがわかりやすいかも。

NSRunLoopがループを回すにあたって決めないといけないのはざっくり2つ。

  • どこからどのように処理を受け取るのか
  • いつまで回しつづけるのか

である。前述のrunMode:beforeDateメソッドはまさにこの2つをパラメータとして受け取る。この記事で解説したような用途に使うループなら、モードはNSDefaultRunLoopMode固定でよい。ループ期限に関しては、前述のように数秒後に自動的に終了という使い方はあまりしないだろう。次のように、NSRunLoopのループ自体をさらにループ内部で実行し、一定間隔でループ終了の判定を行う、というのがよくある使い方である。

詳解 Objective-C 2.0 第3版

必読。こんなゴミサイトより、こっちを読むべき。

Amazonでみる

iPhoneプログラミングUIKit詳解リファレンス

必読。こんなゴミサイトより、こっちを読むべき。

Amazonでみる