Hatena::Groupiphone-dev

Horigoodの日記

2009-08-07

複数のNSTimerを同時に動かす

00:26

OS-Xアプリを作っていたときに、こちらのページ

http://blog.cocoa-study.com/?eid=262567

で教えていただいたものを、現行のiPhoneマニュアルを参考に若干修正して使っています。

今のところ、問題なく動作しています。

timerA = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self
                                   selector:@selector(selectorA)
                                   userInfo:nil
                                   repeats:YES];
/**タイマー1つであれば上記だけでOK**/

/**複数タイマーを非同期で動かすには下記が必要**/
[[NSRunLoop currentRunLoop] addTimer: timerA forMode:NSDefaultRunLoopMode]; 


/**以下、2つめのタイマー**/
timerB = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self
                                   selector:@selector(selectorB)
                                   userInfo:nil
                                   repeats:YES];
[[NSRunLoop currentRunLoop] addTimer: timerB forMode:NSDefaultRunLoopMode]; 

paellapaella2009/08/08 21:17このNSTimerを使ったことがないのですが、たとえば1秒間隔のタイマーで呼ばれたメソッドで「sleep(1);」や時間のかかる処理をするとどうなるんでしょうか?

思い付く範囲では、
1) 次のタイマー発動が、呼ばれたメソッドが終了してから1秒後に始まる(→タイマーが段々ずれてくる)
2) メソッドが呼ばれている最中でも、次のタイマー発動のメソッドが呼ばれる(→メソッドがマルチスレッドセーフでないと危険)
3) メソッドが呼ばれている最中のタイマー発動は無視される(→マルチスレッドには安全だけど、処理が飛ばされる可能性有り)

があるかなと思いまして。
・・・すみません、自分でも試してみますね。

horigoodhorigood2009/08/08 21:55私は素人なものですから、paellaさんのような方を納得させられるテスト法はよくわからないのですが、使用している感覚では(1)だと思います。すいませんアバウトで。

paellapaella2009/08/09 00:08いえいえ、私の方が素人ですよ。タイマー周りの処理は本業の組み込み開発では気を付けないといけない部分なので、たまたまです。

調べたらまたコメントしますね。失礼しました。

paellapaella2009/08/09 00:24何度もすみません。試したら、horigoodさんの仰るとおり1でした。
提示されたソースに以下のメソッドを追加して、

- (void)aSelector {
NSLog(@"Timer expired.");
sleep(1); // ここで1秒の待ち(重い処理と仮定)
}

それで実行してみたところ、ぴったり2秒ごとにログが表示されました。
となると、タイマーイベントの中では処理を出来るだけ軽くすることが必要ですね。

考えるきっかけを与えていただいて、ありがとうございました。

horigoodhorigood2009/08/09 11:27ああ、とりあえずこの件では、そのシンプルなテストでよかったんですね。W
検証していただいて、ありがとうございました。

ちなみに、本エントリの主題である「複数のNSTimer」を、ソース内2つめの [[NSRunLoop currentRunLoop] addTimer: なしで使用した場合、さらに処理が遅れるはずです。

horigoodhorigood2009/08/09 12:41タイトルで「複数の」としておいてソース内に1つではわかりにくい、ということに今さらながら気付きましたので追記しました。