利用NSInvocation对方法进行抽象,实现对方法的加锁

来源:互联网 发布:心脏支架 知乎 编辑:程序博客网 时间:2024/05/01 13:21

我们在实际开发中需要对离散的方式加锁实现线程安全,当然我们有多种实现方式,这只是其中一种,使用起来比较方便


+ (id)performSelectorWithTarget:(id)target selector:(SEL)selector withObject:(id)arg1 ,...NS_REQUIRES_NIL_TERMINATION;

{

    @synchronized(self){

        id result =nil;

        NSMethodSignature *sig = [targetmethodSignatureForSelector:selector];

        if (!sig)return result;

        

        NSInvocation* myInvocation = [NSInvocationinvocationWithMethodSignature:sig];

        [myInvocation setTarget:target];

        [myInvocation setSelector:selector];

        int argumentStart =2;

        va_list args;

        va_start(args, arg1);// scan for arguments after firstObject.

        

        // get rest of the objects until nil is found

        for (id obj = arg1; obj !=nil; obj = va_arg(args,id)) {

            [myInvocation setArgument:&objatIndex:argumentStart];

            argumentStart++;

        }

        

        va_end(args);

        

        [myInvocation retainArguments];

        [myInvocation invoke];

        

        //获得返回值类型

        constchar *returnType = sig.methodReturnType;

        

        //声明返回值变量

        //如果没有返回值,也就是消息声明为void,那么returnValue=nil

        

        if( !strcmp(returnType,@encode(void)) ){

            

            result =  nil;

        }

        

        //如果返回值为对象,那么为变量赋值

        elseif( !strcmp(returnType,@encode(id)) ){

            [myInvocation getReturnValue: &result];

        }else{

            

            //如果返回值为普通类型NSInteger  BOOL

            //返回值长度

            

            NSUInteger length = [sigmethodReturnLength];

            

            //根据长度申请内存

            void *buffer = (void *)malloc(length);

            

            //为变量赋值

            

            [myInvocation getReturnValue:buffer];

            

            if( !strcmp(returnType,@encode(BOOL)) ) {

                

                result = [NSNumbernumberWithBool:*((BOOL*)buffer)];

            }

            elseif( !strcmp(returnType,@encode(NSInteger)) ){

                

                result = [NSNumbernumberWithInteger:*((NSInteger*)buffer)];

            }else {

                result = [NSValuevalueWithBytes:buffer objCType:returnType];

            }

            

            free(buffer);

        }

        return result;

    }

}

0 0