detachNewThreadSelector 方法

今天一个小伙伴问我以下代码会不会打印"—"

[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];
   });
  1. 保证新的线程不被释放
    我们需要添加为子线程添加一个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] 进入睡眠

你可能感兴趣的:(detachNewThreadSelector 方法)