利用NSInvocation对方法进行抽象,实现对方法的加锁
我们在实际开发中须要对离散的方式加锁实现线程安全,当然我们有多种实现方式,这仅仅是当中一种,使用起来比較方便
+ (id)performSelectorWithTarget:(id)target selector:(SEL)selector withObject:(id)arg1 ,...NS_REQUIRES_NIL_TERMINATION;
{
@synchronized(self){
id result = nil;
NSMethodSignature *sig = [target methodSignatureForSelector:selector];
if (!sig) return result;
NSInvocation* myInvocation = [NSInvocation invocationWithMethodSignature: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:&obj atIndex:argumentStart];
argumentStart++;
}
va_end(args);
[myInvocation retainArguments];
[myInvocation invoke];
//获得返回值类型
const char *returnType = sig.methodReturnType;
//声明返回值变量
//假设没有返回值,也就是消息声明为void,那么returnValue=nil
if( !strcmp(returnType, @encode(void)) ){
result = nil;
}
//假设返回值为对象。那么为变量赋值
else if( !strcmp(returnType, @encode(id)) ){
[myInvocation getReturnValue: &result];
}else{
//假设返回值为普通类型NSInteger BOOL
//返回值长度
NSUInteger length = [sig methodReturnLength];
//依据长度申请内存
void *buffer = (void *)malloc(length);
//为变量赋值
[myInvocation getReturnValue:buffer];
if( !strcmp(returnType, @encode(BOOL)) ) {
result = [NSNumber numberWithBool:*((BOOL*)buffer)];
}
else if( !strcmp(returnType, @encode(NSInteger)) ){
result = [NSNumber numberWithInteger:*((NSInteger*)buffer)];
}else {
result = [NSValue valueWithBytes:buffer objCType:returnType];
}
free(buffer);
}
return result;
}
}