iOS runloop 理解及知识点整理

142 阅读1分钟

关于runloop的深入理解,可以参考文章

runloop是执行在线程中的一个循环,通过系统调用和进程间通讯使线程在用户栈与内核栈间切换,从而实现线程的阻塞与激活,空闲时既不执行也退出,激活后执行一次循环后再次阻塞

下面是关于OC层面3个runloop运行函数的理解:

  • runMode:beforeDate:这个函数只会执行一次

    Runs the loop once, blocking for input in the specified mode until a given date. A timer is not considered an input source and may fire multiple times while waiting for this method to return

  • run:无限循环

  • runUntilDate: 设置结束时间,超时自动结束循环

应用比如异步获取userAgent:

[uaWebView evaluateJavaScript:@"navigator.userAgent" 
           completionHandler:^(id _Nullable obj, NSError * _Nullable 
           error) { 
            userAgentStr = obj; end = YES; 
}]; 

while (!end) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
        beforeDate:[NSDate distantFuture]];
}

使用CoreFoundation中的CFRunLoopRunInMode函数(调用CFRunLoopRunSpecific),可以不加循环实现(猜测主函数是如此实现的)

注意: CFRunLoopRunInMode 这个方法的参数 mode 不能是 kCFRunLoopCommonModes, 因为源码里面的逻辑就是这样,如果为kCFRunLoopCommonModes,直接返回kCFRunLoopRunFinished。
CFRunLoopRunSpecific源码:

SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) {     /* DOES CALLOUT */
    CHECK_FOR_FORK();
    if (modeName == NULL || modeName == kCFRunLoopCommonModes || CFEqual(modeName, kCFRunLoopCommonModes)) {
        ...
        return kCFRunLoopRunFinished;
    }
    ....
}