系統(tǒng)的performSelector方法##
在<NSObject> 的協(xié)議中為我們調(diào)用SEL方法提供了幾個(gè)協(xié)議方法
- (id)performSelector:(SEL)aSelector; //直接調(diào)用方法
- (id)performSelector:(SEL)aSelector withObject:(id)object;//可以傳入一個(gè)參數(shù)
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; //可以傳入兩個(gè)參數(shù)
so风范,問題來了捍歪,要是我們需要傳入得參數(shù)大于兩個(gè)怎么辦澈蝙?所以我就試試模擬系統(tǒng)調(diào)用方法的過程來實(shí)現(xiàn)調(diào)用方法可以傳入多個(gè)參數(shù)的demo
系統(tǒng)的performSelector怎么調(diào)用的呢?##
第一步:根據(jù)SEL去實(shí)例化方法簽名NSMethodSignature(方法簽名中有方法的名稱誓军,參數(shù)和返回值)
NSMethodSignature *signature =[[self class] instanceMethodSignatureForSelector:aSelector];
第二步:判斷方法簽名是否存在听想,如果不存在琼掠,就不存在這個(gè)方法腋腮,如果存在,就通過簽名拿到NSInvocation對(duì)象(NSInvocation中保存了方法所屬于的對(duì)象|方法名稱|參數(shù)|返回值等)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
第三步:判斷參數(shù)個(gè)數(shù)纺阔,設(shè)置NSInvocation的對(duì)象設(shè)置參數(shù)瘸彤,調(diào)用方法
這里注意哦
!5讯邸V士觥!玻靡!簽名中方法參數(shù)的個(gè)數(shù):簽名內(nèi)部包含了self和_cmd结榄,所以參數(shù)從第3個(gè)開始
[invocation setTarget:self];
[invocation setSelector:aSelector];
//簽名中方法參數(shù)的個(gè)數(shù),內(nèi)部包含了self和_cmd囤捻,所以參數(shù)從第3個(gè)開始
NSInteger signatureParamCount = methodSignature.numberOfArguments - 2;
NSInteger requireParamCount = objects.count;
NSInteger resultParamCount = MIN(signatureParamCount, requireParamCount);
for (NSInteger i = 0; i < resultParamCount; i++)
{
id obj = objects[i];
[invocation setArgument:&obj atIndex:i+2];
}
[invocation invoke];
第四步:返回值的處理
id callBackObject = nil;
if(methodSignature.methodReturnLength)
{
[invocation getReturnValue:&callBackObject];
}
return callBackObject;
步驟原理說完了臼朗,直接代碼,代碼親切##
個(gè)人建議把這個(gè)方法增加到NSObject的分類中蝎土,以后方便調(diào)用
溫馨提示:代碼復(fù)制可用视哑,要是喜歡就點(diǎn)個(gè)贊。
- (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects
{
NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:aSelector];
if(methodSignature == nil)
{
@throw [NSException exceptionWithName:@"拋異常錯(cuò)誤" reason:@"沒有這個(gè)方法誊涯,或者方法名字錯(cuò)誤" userInfo:nil];
return nil;
}
else
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setTarget:self];
[invocation setSelector:aSelector];
//簽名中方法參數(shù)的個(gè)數(shù)挡毅,內(nèi)部包含了self和_cmd,所以參數(shù)從第3個(gè)開始
NSInteger signatureParamCount = methodSignature.numberOfArguments - 2;
NSInteger requireParamCount = objects.count;
NSInteger resultParamCount = MIN(signatureParamCount, requireParamCount);
for (NSInteger i = 0; i < resultParamCount; i++) {
id obj = objects[i];
[invocation setArgument:&obj atIndex:i+2];
}
[invocation invoke]暴构;
//返回值處理
id callBackObject = nil;
if(methodSignature.methodReturnLength)
{
[invocation getReturnValue:&callBackObject];
}
return callBackObject;
}
}