一、什么是RunLoop图贸?
RunLoop是通過內(nèi)部維護(hù)的事件循環(huán)來對事件/消息進(jìn)行管理的一個(gè)對象蹂季。
1、沒有消息需要處理時(shí)疏日,休眠以避免資源占有偿洁。
2、有消息需要處理時(shí)沟优,立刻被喚醒涕滋。
二、RunLoop的數(shù)據(jù)結(jié)構(gòu)
NSRunLoop是CFRunLoop的封裝挠阁,提供了面向?qū)ο蟮腁PI宾肺。
開源代碼地址:http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz
1、CFRunLoop
(1)侵俗、pthread:一一對應(yīng)(RunLoop和線程的關(guān)系)
(2)锨用、currentModel:CFRunLoopModel
(3)、models:NSMutableSet<CFRunLoopModel*>
(4)隘谣、commonModels:NSMutableSet<NSString*>
1>增拥、CommonModel不是實(shí)際存在的一種Model。
2>寻歧、是同步Source/Timer/Observer到多個(gè)Model中的一種技術(shù)方案跪者。
(5)、commonModelItems:包含Observer熄求、Timer渣玲、Source
2、CFRunLoopModelItems
3弟晚、Source/Timer/Observer
1>忘衍、CFRunLoopSource
source0:需要手動(dòng)喚醒線程。
source1:具備喚醒線程的能力卿城。
2>枚钓、CFRunLoopTimer
基于事件的定時(shí)器,和NSTimer是toll-free bridged的瑟押。
3>搀捷、CFRunLoopObserver
觀測時(shí)間點(diǎn)
KCFRunLoopEntry
KCFRunLoopBeforeTimers
KCFRunLoopBeforeSources
KCFRunLoopBeforeWaiting
KCFRunLoopAfterWaiting
KCFRunLoopExit
三、RunLoop事件循環(huán)機(jī)制的實(shí)現(xiàn)
四、RunLoop與NSTimer
滑動(dòng)TableView的時(shí)候嫩舟,我們的定時(shí)器還會生效嗎氢烘?
Model發(fā)生切換,從KCFRunLoopDefaultModel切換到UITrackingRunLoopModel
五家厌、RunLoop與多線程
1播玖、咋樣實(shí)現(xiàn)一個(gè)常駐線程
(1)、為當(dāng)前線程開啟一個(gè)RunLoop饭于。
(2)蜀踏、向該RunLoop中添加一個(gè)Port/Source等維持RunLoop的事件循環(huán)。
(3)掰吕、啟動(dòng)該RunLoop果覆。
2、RunLoop和線程關(guān)系
(1)殖熟、runloop與線程是一一對應(yīng)的局待,一個(gè)runloop對應(yīng)一個(gè)核心的線程,為什么說是核心的吗讶,是因?yàn)閞unloop是可以嵌套的燎猛,但是核心的只能有一個(gè)恋捆,他們的關(guān)系保存在一個(gè)全局的字典里照皆。
(2)、runloop是來管理線程的沸停,當(dāng)線程的runloop被開啟后膜毁,線程會在執(zhí)行完任務(wù)后進(jìn)入休眠狀態(tài),有了任務(wù)就會被喚醒去執(zhí)行任務(wù)愤钾。
(3)瘟滨、runloop在第一次獲取時(shí)被創(chuàng)建,在線程結(jié)束時(shí)被銷毀能颁。
(4)杂瘸、對于主線程來說,runloop在程序一啟動(dòng)就默認(rèn)創(chuàng)建好了伙菊。
(5)败玉、對于子線程來說,runloop是懶加載的镜硕,只有當(dāng)我們使用的時(shí)候才會創(chuàng)建运翼。
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)、子線程中使用定時(shí)器兴枯,需將定時(shí)器添加至RunLoop中血淌,確保子線程的runloop被創(chuàng)建,不然定時(shí)器不會回調(diào)财剖。
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
//此種方式創(chuàng)建的timer已經(jīng)添加到NSRunloop中了
NSTimer *timer1 =[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
//此種方式創(chuàng)建的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];
});