今天一个小伙伴问我以下代码会不会打印"—"
[NSThread detachNewThreadSelector:@selector(runA:) toTarget:self withObject:@"分离子线程"];
-(void)runA:(NSString *)param {
[self performSelector:@selector(onTask) withObject:nil afterDelay:2.0];
}
-(void)onTask {
NSLog(@"—");
}
答案当然是不能。
我之前在说过类似的问题,在一个新的线程中 延迟2s对self发送消息。发现无论怎么发送这个通知,通知都不会回调,这个是因为并没有为该子线程添加runloop,这个线程触发之后马上就结束了。(没有添加通知队列的时候,是可以回调到的,因为那种情况下,通知发送后,通知回调马上就会执行,该线程会等待通知回调执行完毕后才结束).
1.我们可以选择获取主线程,在主线程中执行该方法
//回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelector:@selector(onTask) withObject:nil afterDelay:2.0];
});
- 保证新的线程不被释放
我们需要添加为子线程添加一个runloop,让子线程常驻:
@property (nonatomic, strong) NSThread *thread;
[self performSelector:@selector(runA:) onThread:self.thread withObject:@"分离子线程" waitUntilDone:YES];
- (NSThread *)thread {
if (!_thread) {
_thread = [[NSThread alloc] initWithBlock:^{
NSRunLoop *ns_runloop = [NSRunLoop currentRunLoop];
[ns_runloop addPort:[NSPort port] forMode:NSRunLoopCommonModes];
CFRunLoopRef runloop = CFRunLoopGetCurrent();
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry:
NSLog(@"进入runLoop");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"处理timer事件");
break;
case kCFRunLoopBeforeSources:
NSLog(@"处理source事件");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"进入睡眠");
break;
case kCFRunLoopAfterWaiting:
NSLog(@"被唤醒");
break;
case kCFRunLoopExit:
NSLog(@"退出");
break;
default:
break;
}
});
CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
CFRelease(observer);
[ns_runloop run];
}];
[_thread start];
}
return _thread;
}
-(void)runA:(NSString *)param
{
NSLog(@"callFunction");
[self performSelector:@selector(onTask) withObject:nil afterDelay:2.0];
}
-(void)onTask {
NSLog(@"—");
}
能清晰的看到log:
2020-04-21 08:45:46.725300+0800 copy[4755:708949] 进入runLoop
2020-04-21 08:45:46.725378+0800 copy[4755:708949] 处理timer事件
2020-04-21 08:45:46.725415+0800 copy[4755:708949] 处理source事件
2020-04-21 08:45:46.725444+0800 copy[4755:708949] callFunction
2020-04-21 08:45:46.725528+0800 copy[4755:708949] 退出
2020-04-21 08:45:46.725608+0800 copy[4755:708949] 进入runLoop
2020-04-21 08:45:46.725640+0800 copy[4755:708949] 处理timer事件
2020-04-21 08:45:46.726288+0800 copy[4755:708949] 处理source事件
2020-04-21 08:45:46.726684+0800 copy[4755:708949] 进入睡眠
2020-04-21 08:45:48.726685+0800 copy[4755:708949] 被唤醒
2020-04-21 08:45:48.727276+0800 copy[4755:708949] —
2020-04-21 08:45:48.728429+0800 copy[4755:708949] 处理timer事件
2020-04-21 08:45:48.729327+0800 copy[4755:708949] 处理source事件
2020-04-21 08:45:48.729693+0800 copy[4755:708949] 进入睡眠