什么是RunLoop
runloop是运行循环,在程序运行过程中循环做一些事情
RunLoop应用范畴
定时器、PerformSelector、GCD 事件响应、手势识别、界面刷新、网络请求、自动释放池
获取RunLoop对象
iOS中有2套API来访问和使用RunLoop,分别是NSRunLoop和CFRunLoopRef 区别是NSRunLoo是基于CFRunLoopRef的一层OC包装
RunLoop与线程的关系
每条线程都有唯一的一个与之对应的RunLoop对象,RunLoop保存在一个全局的Dictionary里 线程作为key,RunLoop作为Value。线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建,RunLoop会在线程结束时销毁。主线程的RunLoop已经自动获取,子线程默认没有开启RunLoop
获取RunLoop对象的方式
Foundation
[NSRunLoop currentRunLoop]; // 获取当前线程的RunLoop对象 [NSRunLoop mainRunLoop]; // 获取主线程
Core Foundation
CFRunLoopGetCurrent();// CF 获取当前线程 CFRunLoopGetMain(); // CF 获取主线程
CFRunLoopModeRef
CFRunLoopModeRef代表RunLoop的运行模式,一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer
RunLoop启动时只能选择其中一个Mode,作为currentMode,如果需要切换Mode,只能退出当前Loop,再重新选择一个Mode进入
不同组的Source0/Source1/Timer/Observer能分隔开来,互不影响,如果Mode里没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出
可以通过如下代码监听loop的状态
CFRunLoopObserverRef observe = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { switch (activity) { case kCFRunLoopEntry: // 进入loop NSLog(@"kCFRunLoopEntry"); break; case kCFRunLoopBeforeTimers: // 即将处理定时器 NSLog(@"kCFRunLoopBeforeTimers"); break; case kCFRunLoopBeforeSources: // 即将处理Source NSLog(@"kCFRunLoopBeforeSources"); break;; case kCFRunLoopBeforeWaiting: // 即将进入休眠 NSLog(@"kCFRunLoopBeforeWaiting"); break;; case kCFRunLoopAfterWaiting: // 即将结束休眠 NSLog(@"kCFRunLoopAfterWaiting"); break; case kCFRunLoopExit: // 即将退出loop NSLog(@"kCFRunLoopExit"); break; default: break; } });