一、什么是RunLoop?
RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象。
1、没有消息需要处理时,休眠以避免资源占有。
2、有消息需要处理时,立刻被唤醒。
![](https://img.haomeiwen.com/i6751716/eac5e68030c21902.png)
![](https://img.haomeiwen.com/i6751716/54471335ba3de0a0.png)
二、RunLoop的数据结构
NSRunLoop是CFRunLoop的封装,提供了面向对象的API。
开源代码地址:http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz
1、CFRunLoop
(1)、pthread:一一对应(RunLoop和线程的关系)
(2)、currentModel:CFRunLoopModel
![](https://img.haomeiwen.com/i6751716/689f95244f419535.png)
(3)、models:NSMutableSet<CFRunLoopModel*>
![](https://img.haomeiwen.com/i6751716/6337d23bf010fa62.png)
(4)、commonModels:NSMutableSet<NSString*>
1>、CommonModel不是实际存在的一种Model。
2>、是同步Source/Timer/Observer到多个Model中的一种技术方案。
(5)、commonModelItems:包含Observer、Timer、Source
2、CFRunLoopModelItems
3、Source/Timer/Observer
1>、CFRunLoopSource
source0:需要手动唤醒线程。
source1:具备唤醒线程的能力。
2>、CFRunLoopTimer
基于事件的定时器,和NSTimer是toll-free bridged的。
3>、CFRunLoopObserver
观测时间点
KCFRunLoopEntry
KCFRunLoopBeforeTimers
KCFRunLoopBeforeSources
KCFRunLoopBeforeWaiting
KCFRunLoopAfterWaiting
KCFRunLoopExit
![](https://img.haomeiwen.com/i6751716/19732207dccce234.png)
三、RunLoop事件循环机制的实现
![](https://img.haomeiwen.com/i6751716/aab2f6686479c01a.png)
![](https://img.haomeiwen.com/i6751716/ac5cdf1437ac1b61.png)
四、RunLoop与NSTimer
滑动TableView的时候,我们的定时器还会生效吗?
Model发生切换,从KCFRunLoopDefaultModel切换到UITrackingRunLoopModel
五、RunLoop与多线程
1、咋样实现一个常驻线程
(1)、为当前线程开启一个RunLoop。
(2)、向该RunLoop中添加一个Port/Source等维持RunLoop的事件循环。
(3)、启动该RunLoop。
2、RunLoop和线程关系
(1)、runloop与线程是一一对应的,一个runloop对应一个核心的线程,为什么说是核心的,是因为runloop是可以嵌套的,但是核心的只能有一个,他们的关系保存在一个全局的字典里。
(2)、runloop是来管理线程的,当线程的runloop被开启后,线程会在执行完任务后进入休眠状态,有了任务就会被唤醒去执行任务。
(3)、runloop在第一次获取时被创建,在线程结束时被销毁。
(4)、对于主线程来说,runloop在程序一启动就默认创建好了。
(5)、对于子线程来说,runloop是懒加载的,只有当我们使用的时候才会创建。
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
[self performSelector:@selector(timerAction) withObject:nil afterDelay:1];
[[NSRunLoop currentRunLoop] run];
});
(6)、子线程中使用定时器,需将定时器添加至RunLoop中,确保子线程的runloop被创建,不然定时器不会回调。
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
//此种方式创建的timer已经添加到NSRunloop中了
NSTimer *timer1 =[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
//此种方式创建的timer没有添加至runloop中
NSTimer *timer2 = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer2 forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
![](https://img.haomeiwen.com/i6751716/6bd6c9e0c839e1f2.png)
网友评论