RunLoop

自己的一些测试结论:

Note:对于 performSelector: 操作,如果没有 afterDelay: 则会在当前线程立即执行;但是如果加了 afterDelay:,则会被添加到相应线程的 RunLoop 中执行。对于 performSelector: 如果有 onThread:,那么该处理也会被添加到指定线程的 RunLoop 中去执行。对于非主线程的其他线程,默认下是没有 RunLoop 的,使用 [NSRunLoop currentRunLoop] 会在当前线程创建 RunLoop,但该 RunLoop 需要手动 run 起来。如果使用 NSTimer 或执行 performSelector: 将对应任务加入到线程的 RunLoop 中,一定要启动对应线程的 RunLoop,即 [[NSRunLoop currentRunLoop] run]

- (void)viewDidLoad {
    [super viewDidLoad];

    [self performSelector:@selector(printYogy) withObject:nil];
    NSLog(@"_missing");
}
- (void)printYogy {
    NSLog(@"yogy....");
}
// 输出为:
// yogy....
// _missing
- (void)viewDidLoad {
    [super viewDidLoad];

    [self performSelector:@selector(printYogy) withObject:nil  :0];
    NSLog(@"_missing");
}
- (void)printYogy {
    NSLog(@"yogy....");
}
// 输出为:
// _missing
// yogy....
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(printYogy) object:nil];
    [thread start];
    [self performSelector:@selector(printHaHa) onThread:thread withObject:nil waitUntilDone:NO];
    
    NSLog(@"_missing");
}
- (void)printYogy {
    // 如果注释下面两行代码,就不会输出 Haha.... 但会输出 yogy... 说明了,
    // performSelector: onThread: 是把操作加到指定线程的 RunLoop 中。且由于 RunLoop 就是在一个线程中执行的,
    // 所以当一个线程的 RunLoop 如果 run 起来,当前线程就进入 run,而等待它返回。(目前它一直都没有返回)
    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"yogy....");
}
- (void)printHaHa {
    NSLog(@"Haha....");
}
// 输出为:
// Haha....
// _missing

Note:对于 Serial Dispatch Queue 使用 waitUntilDone:YES 同样有效。其实,performSelector: 操作都是相对于指定线程的 RunLoop 来说的,所以与 Dispatch Queue 没有任何联系。这里只是说明了:一个线程可以对自己使用 waitUntilDone:YES

- (void)viewDidLoad {
    [super viewDidLoad];

    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"...queue");
        [self performSelector:@selector(printYogy)
                     onThread:[NSThread currentThread]
                   withObject:nil
                waitUntilDone:YES];
        NSLog(@"_missing");
    });
    
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"...main");
}

- (void)printYogy {
    [NSThread sleepForTimeInterval:2.0];
    NSLog(@"yogy....");
}
// 输出为:
// ...main
// ...queue
// yogy....
// _missing

参考资料:
深入理解RunLoop
RunLoop基础元素解析
【iOS程序启动与运转】- RunLoop个人小结
NSTimer和Runloop的关系

你可能感兴趣的:(RunLoop)