dispatchのcancelの方法を実践してみる
別スレッドでタイマーなど処理を行いたい場合にカーネルに登録できるGCDを使用できます。
このGCDはキャンセルもできるのですが、
今回は、他のクラスからcancelをしたいと思ったのでそのような書き方をしています。
正しい書き方かは分かりませんが、備忘録として残しておきます。
@implementation HogehogeClass //staticにして、Cancelできるようにしておく static dispatch_source_t _source; + (void)setTimer:(NSDate *)date block:(void(^)(void))block{ //deltaIntervalを取得して渡してあげる NSTimeInterval deltaInterval = [date timeIntervalSinceDate:[NSDate date]]; [self asyncAfterDelay:deltaInterval block:block]; } + (void)asyncAfterDelay:(NSTimeInterval)delay block:(void(^)(void))block { return [self asyncAfterDate:[NSDate dateWithTimeIntervalSinceNow:delay] block:block]; } + (void)asyncAfterDate:(NSDate *)date block:(void(^)(void))block { __block dispatch_queue_t _queue = dispatch_queue_create("jp.co.hoge.HogeHoge", NULL); //staticで宣言しておいたもの _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _queue); dispatch_source_set_event_handler(_source, ^{ dispatch_async(dispatch_get_main_queue(), ^{ //時間になったら呼ばれるもの block(); //呼ばれたら処理をキャンセルします if (_source) { dispatch_source_cancel(_source); } }); }); dispatch_time_t delta = getDispatchTimeByDate(date); dispatch_source_set_timer(_source, delta, NSEC_PER_SEC, 0); dispatch_resume(_source); } //ここのClassを呼ぶ事で実行中の処理をCancelできます。 + (void)cancelTimer { if (_source) { dispatch_source_cancel(_source); } } dispatch_time_t getDispatchTimeByDate(NSDate *date) { NSTimeInterval interval; double second, subsecond; struct timespec time; dispatch_time_t milestone; interval = [date timeIntervalSince1970]; subsecond = modf(interval, &second); time.tv_sec = second; time.tv_nsec = subsecond * NSEC_PER_SEC; milestone = dispatch_walltime(&time, 0); return milestone; } @end
他のクラスでCancelしたいときはこのように呼ぶ
[HogehogeClass cancelTimer];
先ほどのタイマーをセットする
[HogehogeClass setTimer:セットしたい時間 block:^{ //時間になったらやりたい処理。(blockで渡す) [self XXXXX]; }];