一、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