1、执行以下代码打印结果是什么?
- (void)interview01 {dispatch_queue_t queue = dispatch_get_global_queue(0, 0);dispatch_async(queue, ^{NSLog(@"1");[self performSelector:@selector(print) withObject:nil afterDelay:3];NSLog(@"3");});}- (void)print {NSLog(@"2");}
打印结果:
~: 1~: 3
原因分析:
performSelector:withObject:afterDelay:方法底层是由定时器实现,而定时器又依赖于RunLoop,子线程的RunLoop默认没有开启,所以这段代码不会打印2。
可以参考 GUNStep 来查看performSelector:withObject:afterDelay:实现逻辑,Foundation-RunLoop.m
如何能够让2打印:
方法一:开启当前线程的RunLoop
- (void)test1 {dispatch_queue_t queue = dispatch_get_global_queue(0, 0);dispatch_async(queue, ^{NSLog(@"1");[self performSelector:@selector(test2) withObject:nil afterDelay:3];NSLog(@"3");// 开启RunLoopNSRunLoop *runLoop = [NSRunLoop currentRunLoop];[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];});}
方法二:使用performSelector:方法调用print
- (void)test4 {dispatch_queue_t queue = dispatch_get_global_queue(0, 0);dispatch_async(queue, ^{NSLog(@"1");[self performSelector:@selector(test2)];NSLog(@"3");});}
原因是performSelector底层原理是消息发送,不受RunLoop的影响。
// obcj源码 - NSObject.mm+ (id)performSelector:(SEL)sel {if (!sel) [self doesNotRecognizeSelector:sel];return ((id(*)(id, SEL))objc_msgSend)((id)self, sel);}
2、执行以下代码打印结果是什么?
- (void)interview02 {NSThread *thread = [[NSThread alloc] initWithBlock:^{NSLog(@"1");}];[thread start];[self performSelector:@selector(print) onThread:thread withObject:nil waitUntilDone:YES];}- (void)print {NSLog(@"2");}
打印结果:
~: 1
报错: ! target thread exited while waiting for the perform
分析:
thread在执行start方法时,会调用block内部代码,打印1。
thread没有开启RunLoop所以在start方法后会退出,所以无法在线程里继续执行任务。
