賢明な皆さんはこんなことは無いかも知れないけど、ハマったので覚え書き
内容はNSTimerがどんなに頑張っても発火しないという現象。
タイトルでお察しかも知れないが、GCDを使っている時にNSTimerを使う時は、ちょっと注意が必要
gcd_asyncの先でTimerの仕掛け方
気がついてしまえば当たり前なんだけど、dispatch_async
での処理は、新しいRunLoopが作られ、使い終わったら破棄される。これがすっぽり抜け落ちていた。
間違ったコード
wrong.m
NSTimer *aTimer = [[NSTimer alloc] initWithFireDate:date interval:seconds target:self selector:@selector(foo:) userInfo:userInfo repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer];
何が間違いかお解りだろうか?
そう!別スレッドにいるにもかかわらず、[NSRunLoop currentRunLoop]
を使ってしまっている.
正解はこう
work.m
NSTimer *aTimer = [[NSTimer alloc] initWithFireDate:date interval:seconds target:self selector:@selector(foo:) userInfo:userInfo repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer];
別にmainRunLoop
じゃなくてもいいんだけど、永続しているRunLoopを取得して、それにタイマーをフックしないとダメ。
じゃあないと、折角しかけたタイマーが、ランループ毎消失してしまって、失火する。
たったこれだけなんだけど、ハマる時はハマるので気をつけよう。