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:の意味が無い。

次回はこの肝心要の非同期処理=別スレッドでの処理実行と他の処理との同期を実装していこう。