我們在實際開發中需要對離散的方式加鎖實作線程安全,當然我們有多種實作方式,這隻是其中一種,使用起來比較友善
+ (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;
}
}