iOS 幾種方法調(diào)用

performSelector

NSObject.h
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

performSelector的使用

1.無(wú)參數(shù)調(diào)用

[self sendMessage];

- (void)sendMessageWithNumber:(NSString *)number {
    NSLog(@"%@",number);
}

2.單個(gè)參數(shù)調(diào)用

 [self sendMessageWithNumber:@"Number"];

- (void)sendMessageWithNumber:(NSString *)number {
    NSLog(@"%@",number);
}

3.兩個(gè)參數(shù)調(diào)用

[self sendMessageWithNumber:@"Number" count:@"count"];

- (id)sendMessageWithNumber:(NSString *)number
                        count:(NSString *)count {
    NSLog(@"%@ %@",number,count);
    
    return nil;
}

performSelector 不能傳遞三個(gè)以及三個(gè)以上的參數(shù)。假如需要傳的話(huà),可以使用 NSInvocation 或者是 objc_msgSend

performSelectorOnMainThread

NSThread.h

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

基于默認(rèn)模式調(diào)用主線(xiàn)程中接收器的方法,該方法不應(yīng)該有明確的返回值并且最多只有一個(gè)id類(lèi)型的參數(shù),或者沒(méi)有參數(shù)。wait指定是否阻塞當(dāng)前線(xiàn)程直到指定選擇器在主線(xiàn)程中執(zhí)行完畢。選擇YES會(huì)阻塞這個(gè)線(xiàn)程;選擇NO,本方法會(huì)立刻返回。如果當(dāng)前線(xiàn)程也是主線(xiàn)程,選擇YES,消息會(huì)立即派發(fā),處理。
``

例如

    NSLog(@"1");
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"2");
        sleep(2);
        NSLog(@"3");
    });
    [self performSelectorOnMainThread:@selector(sendMessageWithNumber:) withObject:@"4" waitUntilDone:YES];

- (void)sendMessageWithNumber:(NSString *)number {
    NSLog(@"%@",number);
}

輸出結(jié)果

1 4 2 3

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thrwithObject:(nullable id)arg waitUntilDone:(BOOL)wait;

調(diào)用指定線(xiàn)程中的某個(gè)方法。

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thrwithObject:(nullable id)arg waitUntilDone:(BOOL)wait;

開(kāi)啟子線(xiàn)程在后臺(tái)運(yùn)行

performSelector afterDelay

NSRunLoop.h
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

這兩個(gè)方法為異步執(zhí)行,即使delay傳參為0,仍為異步執(zhí)行。只能在主線(xiàn)程中執(zhí)行,在子線(xiàn)程中不會(huì)調(diào)到aSelector方法。可用于當(dāng)點(diǎn)擊UI中一個(gè)按鈕會(huì)觸發(fā)一個(gè)消耗系統(tǒng)性能的事件,在事件執(zhí)行期間按鈕會(huì)一直處于高亮狀態(tài),此時(shí)可以調(diào)用該方法去異步的處理該事件,就能避免上面的問(wèn)題。

在方法未到執(zhí)行時(shí)間之前,取消方法為:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
注意:調(diào)用該方法之前或在該方法所在的viewController生命周期結(jié)束的時(shí)候去調(diào)用取消函數(shù),以確保不會(huì)引起內(nèi)存泄露。

例如

NSLog(@"1");
    [self performSelector:@selector(sendMessageWithNumber:) withObject:@"2" afterDelay:3];
    NSLog(@"3");

打印出 1 3 2
而如下則打印出 1 3

dispatch_async(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^{
        NSLog(@"1");
          [self performSelector:@selector(sendMessageWithNumber:) withObject:@"2" afterDelay:3];
          NSLog(@"3");
    });
 NSLog(@"1");
    [self performSelector:@selector(sendMessageWithNumber:) withObject:@"2" afterDelay:3];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(sendMessageWithNumber:) object:@"2"];
    NSLog(@"3");

打印結(jié)果 1 3,因?yàn)榇蛴?code>2的事件已經(jīng)在執(zhí)行前被取消了

NSInvocation

SEL selector = @selector(sendMessageWithNumber:count:);
//    方法簽名
    NSMethodSignature *singnature = [self methodSignatureForSelector:selector];
    if (singnature) {
        // NSInvocation : 利用一個(gè)NSInvocation對(duì)象包裝一次方法調(diào)用(方法調(diào)用者、方法名、方法參數(shù)、方法返回值)
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:singnature];
        [invocation setTarget:self];
        [invocation setSelector:@selector(sendMessageWithNumber:count:)];
        
        NSString *number = @"1111";
        NSString *number2 = @"2ss";
        
         // 設(shè)置參數(shù)
        [invocation setArgument:&number atIndex:2];
        [invocation setArgument:&number2 atIndex:3];
        
        // 調(diào)用方法
        [invocation invoke];
        
        // 獲取返回值
        NSString *result;
        if (singnature.methodReturnLength != 0) {// 有返回值類(lèi)型,才去獲得返回值
            [invocation getReturnValue:&result];
        }
        
        NSLog(@"%@",result);
    } else {
         //可以?huà)伋霎惓R部梢圆徊僮鳌?        NSLog(@"singnature is nil");
    }

調(diào)用時(shí)可以傳入多個(gè)參數(shù);

但是要注意判斷是否是簽名成功;

因?yàn)榍皟蓚€(gè)參數(shù)分別是方法調(diào)用者、方法名,因?yàn)樽约簜魅氲膮?shù)是從第三個(gè)開(kāi)始;

objc_msgSend

objc_msgSend

SEL selector = @selector(sendMessageWithNumber:count:);
    NSString *result = ((NSString * (*) (id, SEL, NSString *, NSString *))objc_msgSend)(self, selector,@"2",@"3");
    NSLog(@"%@",result);

打印結(jié)果如下

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

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

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