一、什么是RunLoop?
RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象。
1、没有消息需要处理时,休眠以避免资源占有。
2、有消息需要处理时,立刻被唤醒。


二、RunLoop的数据结构
NSRunLoop是CFRunLoop的封装,提供了面向对象的API。
开源代码地址:http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz
1、CFRunLoop
(1)、pthread:一一对应(RunLoop和线程的关系)
(2)、currentModel:CFRunLoopModel

(3)、models:NSMutableSet<CFRunLoopModel*>

(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

三、RunLoop事件循环机制的实现


四、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];
});

网友评论