原文連結:http://www.jianshu.com/p/0c45b496686a
字數682 閱讀263 評論4 喜歡2
開發中偶爾有需求使用performSelector實作多個參數,
正常的方式是自定義一個performSelector方法并接收一個數組作為參數
在方法内部通過周遊數組,擷取方法的參數,這确實是個好方法,
不過當我們需要給某個參數傳遞nil的時候,這個方法就不适用了,因為數組中不能存nil
下面嘗試一種非正常的方法,請看~
/// 該方法接收一個方法的簽名,和一個可變參數
- (id)performSelector:(SEL)aSelector withObjects:(id)object,... {
// 方法簽名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector];
if (signature == nil) {
NSAssert(false, @"牛逼的錯誤,找不到 %@ 方法",NSStringFromSelector(aSelector));
}
// 包裝方法
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
// 設定方法調用者
invocation.target = self;
// 設定需要調用的方法
invocation.selector = aSelector;
// 擷取除去self、_cmd以外的參數個數
NSInteger paramsCount = signature.numberOfArguments - ;
// 設定參數
va_list params;
va_start(params, object);
int i = ;
// [GKEndMark end] 是自定義的結束符号,僅此而已,進而使的該方法可以接收nil做為參數
for (id tmpObject = object; (id)tmpObject != [GKEndMark end]; tmpObject = va_arg(params, id)) {
// 防止越界
if (i >= paramsCount) break;
// 去掉self,_cmd是以從2開始
[invocation setArgument:&tmpObject atIndex:i + ];
i++;
}
va_end(params);
// 調用方法
[invocation invoke];
// 擷取傳回值
id returnValue = nil;
if (signature.methodReturnType) {
[invocation getReturnValue:&returnValue];
}
return returnValue;
}
下面是自定義的結束符号類的具體實作
#import "GKEndMark.h"
@implementation GKEndMark
+ (instancetype)end {
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self class] new];
});
return instance;
}
@end
具體使用
- (void)viewDidLoad {
[super viewDidLoad];
// [GKEndMark end] 為自定義的結束符号,你也可以自己随便自定義一個~ 隻是為了讓參數可以傳nil
NSString * resultStr = [self performSelector:@selector(resultStringWithStr1:str2:str3:) withObjects:@"大神",nil,@"帶我飛",@"飛飛飛",[GKEndMark end]];
NSLog(@"輸出結果 %@",resultStr);
}
- (NSString *)resultStringWithStr1:(NSString *)str1 str2:(NSString *)str2 str3:(NSString *)str3 {
NSLog(@"各參數的值: str1 = %@ , str1 = %@, str1 = %@",str1, str2, str3);
NSString * str = str1;
if (str2) {
str = [str1 stringByAppendingString:str2];
}
if (str3) {
return [str stringByAppendingString:str3];
}
return str;
}
控制台輸出結果如下
Paste_Image.png
以上為方法的具體實作,已經做了詳細的注釋了,就不多做解釋了,
不過該方法還有個局限性就是
當調用的方法傳回值不是對象類型時就會崩了
(不過系統的這類似的方法也沒有傳回基本資料類型的,不知道是不是我想太多了)
想了蠻久不知道該如何解決,如果你有好的解決方案,請聯系我,謝謝~
需要用到資料庫的請看:http://www.jianshu.com/p/0e598147debc