有時(shí)候你會(huì)發(fā)現(xiàn)performSelector延時(shí)不起作用,啥原因呢
先看下面的例子
- (void)viewDidLoad {
[super viewDidLoad];
NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil];
[thread setName:@"com.will.thread"];
[thread start];
}
- (void)threadRun{
[self performSelector:@selector(runTime1) withObject:nil];
[self performSelector:@selector(runTime2) withObject:nil afterDelay:1];
[self performSelector:@selector(runTime2) withObject:nil afterDelay:1 inModes:@[NSDefaultRunLoopMode]];
}
- (void)runTime1{
NSLog(@"xxoo1");
}
- (void)runTime2{
NSLog(@"xxoo2");
}

image.png
為什么延時(shí)函數(shù)沒(méi)有調(diào)用,因?yàn)槟阍谧泳€程里調(diào)用延時(shí)函數(shù),需要定時(shí)器,而子線程不同于主線程不會(huì)自動(dòng)創(chuàng)建runloop,導(dǎo)致定時(shí)器沒(méi)有工作,
解決方法有四種:
- 在子線程里啟動(dòng)runloop
- (void)threadRun{
[self performSelector:@selector(runTime2) withObject:nil afterDelay:1];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
- performSelector設(shè)定主線程,不過(guò)沒(méi)法設(shè)置延時(shí)函數(shù)
- (void)threadRun{
[self performSelector:@selector(runTime2) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];
//或者:
[self performSelectorOnMainThread:@selector(runTime2) withObject:nil waitUntilDone:NO];
}
- 專門設(shè)定在已經(jīng)開(kāi)啟了runloop的線程
- (void)threadRun{
[self performSelector:@selector(runTime2) onThread:[[self class] _networkThread] withObject:nil waitUntilDone:NO modes:@[NSDefaultRunLoopMode]];
}
+ (void)_addRunLoop:(NSThread *)thread{
@autoreleasepool {
[[NSThread currentThread] setName:@"com.will.webimage.request"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
+ (NSThread *)_networkThread{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(_addRunLoop:) object:nil];
[NSThread sleepForTimeInterval:1];
[thread start];
return thread;
}
- 直接用GCD的延時(shí)方法
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self runTime2];
});
注意:
performSelector若不指定mode([self performSelector:@selector(method) withObject:nil];),默認(rèn)自動(dòng)創(chuàng)建mode為NSDefaultRunLoopModeperformSelector:onThread:withObject:waitUntilDone里waitUntilDone為NO,則會(huì)等待當(dāng)前線程執(zhí)行完,再執(zhí)行selector里的方法
- (void)threadRun{
[self performSelector:@selector(runTime2) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO];
NSLog(@"com.will.thread執(zhí)行完畢");
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
打印如下

image.png