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;
});
}
}