Objective-C
iOS
GCD

ディスパッチグループを使ってタイムアウトつきインジケータの表示

More than 5 years have passed since last update.

GCDのグループ機能を使ってタスクを同期してみた例。500ミリ秒以内に終わる場合はインジケータを表示しないような処理。

- (IBAction)anAction:(id)sender

{
dispatch_queue_t q_global, q_main;
static BOOL busy = NO;

if (!busy) {
busy = YES;
q_global = dispatch_get_global_queue(0, 0); // 計算用の非同期キュー
q_main = dispatch_get_main_queue(); // 描画用のメインキュー
dispatch_group_t grp = dispatch_group_create(); // タスク同期用のグループ作成

// メインの処理を同期用のグループにディスパッチ
dispatch_group_async(grp, q_global, ^{
// タイムアウト用のタスクはグループには追加しない
dispatch_async(q_global, ^{
if (dispatch_group_wait(grp, dispatch_time(DISPATCH_TIME_NOW, 500*1000*1000))) { // 500ミリ秒待ってやる

// インジケータを用意
UIActivityIndicatorView *indicator;
indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.contentMode = UIViewContentModeCenter;
indicator.center = self.tvResults.center;
indicator.hidesWhenStopped = TRUE;
[indicator startAnimating];

dispatch_async(q_main, ^{
// インジケータを表示
[self.view addSubview:indicator];
});

// グループの終了を待ってインジケータを消去
dispatch_group_notify(grp, q_main, ^{
[indicator removeFromSuperview];
[indicator release];
dispatch_release(grp); // グループの解放
});
} else {
dispatch_release(grp);
}
});

heavyWork(); // 時間のかかる処理

// 結果の表示
dispatch_group_async(grp, q_main, ^{
[self.tvResults reloadData];
});
busy = NO;
});

}
}