performSelector 和NSTimer使用注意事項(xiàng)

一、performSelectorXXX之類的方法

1、performSelectorOnMainThread:withObject:waitUntilDone:

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

在主線程上執(zhí)行指定的方法,使用默認(rèn)的模式(NSDefaultRunLoopMode)。
默認(rèn)的模式指:主線程中的方法進(jìn)行排隊(duì),是一個(gè)循環(huán)隊(duì)列,并且循環(huán)執(zhí)行。
參數(shù):
aSelector:要在主線程執(zhí)行的方法,該方法不能有返回值,并且只能有一個(gè)參數(shù)。
arg:要傳遞的參數(shù),如果無參數(shù),就設(shè)為nil
wait:要執(zhí)行的aSelector方法,是否馬上執(zhí)行。
如果設(shè)置為YES:等待當(dāng)前線程執(zhí)行完以后,主線程才會(huì)執(zhí)行aSelector方法;
設(shè)置為NO:不等待當(dāng)前線程執(zhí)行完,就在主線程上執(zhí)行aSelector方法。
如果,當(dāng)前線程就是主線程,那么aSelector方法會(huì)馬上執(zhí)行。

該方法用途:因?yàn)閕Phone編程,對(duì)UI的修改,只能在主線程上執(zhí)行。可以用該方法來完成UI的修改。

2、performSelector:withObject:afterDelay:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

在當(dāng)前線程中執(zhí)行指定的方法,使用默認(rèn)模式,并指定延遲。
參數(shù):
aSelector:指定的方法。含義同上,不在贅述。
anArgument:同上
delay:指定延遲時(shí)間(秒)。

3、performSelector
我們常常用到以下3個(gè)方法,分別為:

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

更多參數(shù)可以封裝字典dictionary再傳。

二、NSTimer

先說一下,初始化方法

+ scheduledTimerWithTimeInterval:invocation:repeats:
+ scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:

這兩個(gè)是創(chuàng)建一個(gè)定時(shí)器,并自動(dòng)加入到當(dāng)前運(yùn)行循環(huán)中,即我們可以這樣去理解,初始化了一個(gè)定時(shí)器時(shí),在(NSTimeInterval)seconds 時(shí)間之后,自動(dòng)啟動(dòng)定時(shí)器。

但而以下兩個(gè)初始化方法這不一樣:

+ timerWithTimeInterval:invocation:repeats:
+ timerWithTimeInterval:target:selector:userInfo:repeats:

這兩個(gè)同樣是創(chuàng)建,但沒有加入到運(yùn)行循環(huán)中,需要手動(dòng)添加,如下:

_timer=[NSTimer timerWithTimeInterval:10 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
 //必須手動(dòng)加入到當(dāng)前循環(huán)中去
NSRunLoop *runloop=[NSRunLoop currentRunLoop];
[runloop addTimer:_timer forMode:NSDefaultRunLoopMode];

三、代碼驗(yàn)證

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1、在主線程執(zhí)行調(diào)用
    [self performSelector:@selector(performOnMainThread) withObject:nil afterDelay:3];
    
    
    
    [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(scheduledTimerOnMainThread) userInfo:nil repeats:YES];
    
    
    //  要讓 timerWithTimeInterval 這個(gè)定時(shí)器執(zhí)行,不行手動(dòng)加到必須手動(dòng)加入到當(dāng)前循環(huán)中去
    /**
     *  [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerWithTimeMethod) userInfo:nil repeats:YES];
    
     *   NSRunLoop *runloop=[NSRunLoop currentRunLoop];
     *   [runloop addTimer:_timer forMode:NSDefaultRunLoopMode];
     *
     */
    
    
    
    [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerWithTimeOnMainThread) userInfo:nil repeats:YES];
    
//    2、在子線程執(zhí)行調(diào)用
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        [self performSelector:@selector(performOnSubThread) withObject:nil afterDelay:3];
        
        
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(scheduledTimerOnSubThread) userInfo:nil repeats:YES];
        
        
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(timerWithTimeOnSubThread) userInfo:nil repeats:YES];
    });
    
    
}

#pragma mark - 延遲執(zhí)行指定方法
- (void)performOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"performOnMainThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}


- (void)performOnSubThread {
    
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"performonSubThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}


- (void)scheduledTimerOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"scheduledTimerOnMainThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)scheduledTimerOnSubThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"scheduledTimerOnSubThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)timerWithTimeOnSubThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"timerWithTimeOnSubThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)timerWithTimeOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主線程":@"子線程";
    NSLog(@"timerWithTimeOnMainThread 方法在 %@ 執(zhí)行",thread);
    NSLog(@"-------------------------------------------------");
}


結(jié)果輸出如下:

2016-08-16 11:30:55.776 performSelector[9788:1950942] performOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:30:55.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:30:55.777 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:30:55.778 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:30:58.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:30:58.776 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:01.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:31:01.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:04.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:31:04.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:07.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主線程執(zhí)行
2016-08-16 11:31:07.776 performSelector[9788:1950942] -------------------------------------------------

四、結(jié)論

performSelector:withObject:afterDelay 和
[NSTimer timerWithTimeInterval:invocation:repeats:]
放在在子線程中指定的@selecter()不會(huì)執(zhí)行,主線程中可正常使用。因此必須保證調(diào)用是在主線程中。因此,可以使用GCD的方式,將此調(diào)用放在主線程中執(zhí)行:
dispatch_async(dispatch_get_main_queue(), ^{ });或者調(diào)用
performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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