2012/04/21

gcdタスクを途中で中断する

iOS上で時間のかかる処理を実行する場合には、GCDを利用してバックグラウンド処理するのが効果的です。 ただ、GCDにはcancelの仕組みがないため、cancel方法は自分で実装する必要があります。

良くあるのは、viewのdidChange系通知を使用する場合です。ユーザレスポンスを高めるためにはdidChangeにはすぐ応答したいですが、ユーザの操作によってはdidChangeは連続して送られてきます。使用されないデータを計算するのは時間的にも消費電力的にも無駄になるため、最後の一回だけを実行することが望ましいです。

僕の場合には、下記のようなキャンセル状態を保存するクラスを作成し、それをGCDで実行するブロックに渡すようにしました。

@interface Sample : NSObject
@property(readonly) BOOL isCanceled;
-(void)cancel;
@end

@implementation Sample
@synthesize isCanceled=_isCanceled;

-(void)cancel
{
  @synchronized(self){
    _isCanceled = true;
  }
}
@end

新しくGCDに処理を投入する場合には、cancelFlagを生成してそれをブロックに渡します。もしすでに使用中のcancelFlagがある場合には、先にロックを取得した上でFlagをキャンセルしておきます。

 -- ジョブは完了済みか、実行中 --
[cancelFlag cancel];
 -- ジョブは完了済みか、キャンセル済み --
cancelFlag = [[Sample alloc]init];

GCDで実行するブロックの中では処理の合間にcancelFlagを確認します。この際に必ずしもロックは必要ありませんが、処理を完了する時には必ずロックを取得することで、ジョブの二重実行をさけることができます。

参考

0 件のコメント:

コメントを投稿