关于runloop的深入理解,可以参考文章
- iOS线程与runloop运转过程,其中关于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;
}
....
}