BBAsyncTask その3
これでBBAsyncTaskクラスは全てのメッセージを捕捉できるようになった。
次回はプロキシ内部の実装を見ていこう。
プロキシ内部の処理だが、以下のようになるはずだ。
1. 呼ばれたようとしているセレクタは"executeInBackgound:"か?
1-1. セレクタ"preExecute:"は記述されているか?
1-1-1. preExecute:実行
1-2. executeInBackgound:実行
1-3. セレクタ"postExecute:"は記述されているか?
1-3-1. postExecute:実行
2. それ以外のセレクタは全て通常通り実行(パススルー)する
オーバライドされるメソッドforwardInvocation:とそこから呼ばれるaSyncExecuteの内容は以下のようになるだろう。
BBBindingTask.m
@implementation _MethodProxy 〜 - (void)forwardInvocation:(NSInvocation*)invocation { if ( [self targetObject] ) { if ( [invocation selector] == @selector(executeInBackgound:) ) { //非同期実行 [self aSyncExecute:invocation]; } else { [invocation setTarget:[self targetObject]]; [invocation invoke]; } } } - (void)aSyncExecute:(NSInvocation*)invocation { // preExecute 実行 SEL pre = @selector(preExecute:); if ( pre && [[self targetObject] respondsToSelector:pre] ) { [inv setTarget:[self targetObject]]; [inv setSelector:pre]; [inv invoke]; } //execute実行 SEL exec = @selector(executeInBackgound:); [inv setTarget:[self targetObject]]; [inv setSelector:exec]; [inv invoke]; //postExecute 実行 SEL post = @selector(postExecute:); if (post && [[self targetObject] respondsToSelector:post]) { __autoreleasing id returnValue; [inv getReturnValue:&returnValue]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [[self targetObject] performSelector:post withObject:returnValue]; #pragma clang diagnostic pop } } @end
一連の#pragma clang diagnostic〜はARCによって出る警告を抑制するもので、処理に影響は無い。
__autoreleasing で修飾された変数があるのは、このプロジェクトがARCで書かれているため。こうしないと戻り値であるreturnValueはスコープを抜けた際に無効な参照になってしまう。
これで具象クラスにpreExecute:やpostExecute:を記述していればexecuteInBackgound:の前後に確実に実行される。
..おっと、このままでは非同期どころかexecuteInBackgound:はメインスレッドで動作してしまうのでexecuteInBackgound:の意味が無い。
次回はこの肝心要の非同期処理=別スレッドでの処理実行と他の処理との同期を実装していこう。