Runtime 應(yīng)用|多參數(shù)傳遞

傳遞不定長的多個參數(shù)

/*iOS實現(xiàn)傳遞不定長的多個參數(shù)的方法是使用va_list。va_list是C語言提供的處理變長參數(shù)的一種方法。在調(diào)用的時候要在參 數(shù)結(jié)尾的時候加nil
    va_list的使用需要注意:
        1.首先在函數(shù)里定義va_list型的變量,這個變量是指向參數(shù)的指針;
        2.然后用va_start初始化剛定義的va_list變量;
        3.然后用va_arg返回可變的參數(shù),va_arg的第二個參數(shù)是你要返回的參數(shù)的類型.如果函數(shù)有多個可變參數(shù)的,依次調(diào)用va_arg獲取各個參數(shù);
        4.最后用va_end宏結(jié)束可變參數(shù)的獲取
        
        NS_REQUIRES_NIL_TERMINATION,是一個宏,用于編譯時非nil結(jié)尾的檢查。 調(diào)用時要以nil結(jié)尾,否則會崩潰。
 
 */
- (void)testParams:(NSString *)title addMoreParams:(NSString *)string, ...NS_REQUIRES_NIL_TERMINATION {
    
    NSLog(@"傳多個參數(shù)的第一個參數(shù) %@",string);//是other1
    
    //1.定義一個指向個數(shù)可變的參數(shù)列表指針;
    va_list args;
    
    //2.va_start(args, str);string為第一個參數(shù),也就是最右邊的已知參數(shù),這里就是獲取第一個可選參數(shù)的地址.使參數(shù)列表指針指向函數(shù)參數(shù)列表中的第一個可選參數(shù),函數(shù)參數(shù)列表中參數(shù)在內(nèi)存中的順序與函數(shù)聲明時的順序是一致的。
    va_start(args, string);
    
    if (string)
    {
        //依次取得除第一個參數(shù)以外的參數(shù)
        //4.va_arg(args,NSString):返回參數(shù)列表中指針?biāo)傅膮?shù),返回類型為NSString,并使參數(shù)指針指向參數(shù)列表中下一個參數(shù)。
        while (va_arg(args, NSString *))
        {
            NSString *otherString = va_arg(args, NSString *);
            NSLog(@"otherString %@",otherString);
        }
    }
    //5.清空參數(shù)列表,并置參數(shù)指針args無效。
    va_end(args);
    
}

performSelector多參數(shù)傳遞解決方案

解決方案:

    1. 使用NSInvocation進行消息轉(zhuǎn)發(fā)從而實現(xiàn)對performSelector的多參數(shù)傳遞。
    1. 使用runtime中的objc_msgSend進行消息的發(fā)送。
方案一:

使用NSInvocation進行消息轉(zhuǎn)發(fā)從而實現(xiàn)對performSelector的多參數(shù)傳遞。

- (void)viewDidLoad {
    [super viewDidLoad];
    id object = [self glt_performSelector:@selector(testMoreArg:arg2:arg3:) withObject:@"username",@"sex",@"height", nil];
    NSLog(@"%@",object);
}

- (NSString *)testMoreArg:(NSString *)arg1 arg2:(NSString *)arg2 arg3:(NSString *)arg3{
    NSLog(@"arg1 = %@ arg2 = %@ arg3 = %@",arg1,arg2,arg3);
    return [NSString stringWithFormat:@"%@%@%@",arg1,arg2,arg3];
}

-(id)glt_performSelector:(SEL)selector withObject:(id)object,...NS_REQUIRES_NIL_TERMINATION{
    //根據(jù)類名以及SEL 獲取方法簽名的實例
    NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
    if (signature == nil) {
        NSLog(@"--- 使用實例方法調(diào)用 為nil ---");
        signature = [self methodSignatureForSelector:selector];
        if (signature == nil) {
            NSLog(@"使用類方法調(diào)用 也為nil, 此時return");
            return nil;
        }
    }
    //NSInvocation是一個消息調(diào)用類,它包含了所有OC消息的成分:target、selector、參數(shù)以及返回值。
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.target = self;
    invocation.selector = selector;
    NSUInteger argCount = signature.numberOfArguments;
    // 參數(shù)必須從第2個索引開始,因為前兩個已經(jīng)被target和selector使用
    argCount = argCount > 2 ? argCount - 2 : 0;
    NSMutableArray *objs = [NSMutableArray arrayWithCapacity:0];
    if (object) {
        [objs addObject:object];
        va_list args;
        va_start(args, object);
        while ((object = va_arg(args, id))){
            [objs addObject:object];
        }
        va_end(args);
    }
    if (objs.count != argCount){
        NSLog(@"--- objs.count != argCount! please check it! ---");
        return nil;
    }
    //設(shè)置參數(shù)列表
    for (NSInteger i = 0; i < objs.count; i++) {
        id obj = objs[i];
        if ([obj isKindOfClass:[NSNull class]]) {
            continue;
        }
        [invocation setArgument:&obj atIndex:i+2];
    }
    [invocation invoke];
    //獲取返回值
    if (signature.methodReturnLength != 0 && signature.methodReturnLength) {
        void *returnValue;
        [invocation getReturnValue:&returnValue];
        return (__bridge id)returnValue;
    }
    return nil;
}
方案二:

參考之前的文章:
Runtime objc_msgSend

參考資料

iOS實現(xiàn)傳遞不定長的多個參數(shù)
iOS performSelector多參數(shù)傳遞解決方案以及objc_msgSend的使用注意事項
NSInvocation在獲取返回值后crash問題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容