一荒椭、RunLoop的基本作用
1.保持程序的持續(xù)運(yùn)行(比如主程序循環(huán)跪另,在啟程動(dòng)main函數(shù)的時(shí)候跪妥,會(huì)在主線程中開啟一個(gè)死循環(huán)岳枷,保證程序能夠一直運(yùn)行)
2.處理程序中的各種事件(用戶交互事件,定時(shí)器事件垒探,Selector事件)
3.在無各種事件觸發(fā)的時(shí)候妓蛮,節(jié)省CPU資源,事件需要時(shí)才調(diào)用CPU
二圾叼、RunLoop的API使用
1.關(guān)于RunLoop的使用有兩套API蛤克,NSRunLoop(OC語言)和CFRunLoopRef(C語言),其中前者是對(duì)后者的封裝
2.一般來說夷蚊,使用NSRunLoop构挤,獲取當(dāng)前線程的RunLoop的方式為[NSRunLoop currentRunLoop]
三、RunLoop在實(shí)際開發(fā)中的使用
RunLoop的常用模式有兩種:NSDefaultRunLoopMode 和 UITrackingRunLoopMode惕鼓,其他模式?jīng)]用或者可用性不大
0.①每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象筋现,主線程的RunLoop在程序開始的main函數(shù)中就已經(jīng)自動(dòng)創(chuàng)建好了 ,子線程的RunLoop需要開發(fā)者主動(dòng)創(chuàng)建
②子線程中的創(chuàng)建 :RunLoop在第一次獲取時(shí)箱歧,即使用[NSRunLoop currentRunLoop]獲取RunLoop時(shí)創(chuàng)建矾飞,在子線程結(jié)束時(shí)銷毀
1.NSTimer定時(shí)器的應(yīng)用
NSTimer默認(rèn)被添加到NSDefaultRunLoopMode模式下。當(dāng)NSTimer處于NSDefaultRunLoopMode時(shí)(比如頁面滑動(dòng))呀邢,定時(shí)器會(huì)在RunLoop會(huì)在其他模式下失效洒沦,直到RunLoop回到NSDefaultRunLoopMode模式,想要NsTimer在其他模式下也可以正常工作价淌,就需要手動(dòng)修改NSTimer在RunLoop下的模式申眼。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
2.ImageView
讓某些事件或行為讓特性模式下執(zhí)行。
像微信中的那樣蝉衣,當(dāng)用戶在滑動(dòng)頁面操作時(shí)括尸,為了減少CPU的使用,保證頁面滑動(dòng)的流暢性病毡,不顯示圖片濒翻,在滑動(dòng)動(dòng)作結(jié)束后方顯示圖片。對(duì)于這樣的功能剪验,就可以使用runloop肴焊,把imageview setImage:這一操作放在NSDefaultRunLoopMode模式下:
[imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"imageName"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
當(dāng)然,也可以監(jiān)聽scrollview的滑動(dòng)功戚。
類似的娶眷,如果有其他類似的需求,都可以調(diào)用 performSelector:withObject: afterDelay: inModes方法
3.保障子線程的存活
在我們不希望我們自己開辟的子線程在完成任務(wù)的時(shí)候就銷毀啸臀,就可以使用RunLoop保障子線程的存活届宠。
操作很簡單,在子線程中調(diào)用
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
//開啟runloop
[[NSRunLoop currentRunLoop] run]; // (不建議使用該方法,無法退出)
或者
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
或者
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
在需要銷毀線程時(shí)乘粒,使用[NSThread exit];
四豌注、補(bǔ)充
NSTimer因?yàn)闀?huì)可能受到Runloop的模式影響,存在時(shí)間不準(zhǔn)時(shí)的情況灯萍。GCD做的定時(shí)器不受RunLoop影響轧铁。不管在子線程還是主線程。
@property (nonatomic, strong) dispatch_source_t timer;
int count = 0;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 根據(jù)實(shí)際情況獲得所需的隊(duì)列
//? ? dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_queue_t queue = dispatch_get_main_queue();
// 創(chuàng)建一個(gè)定時(shí)器(dispatch_source_t本質(zhì)還是個(gè)OC對(duì)象)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 設(shè)置定時(shí)器的各種屬性(幾時(shí)開始任務(wù)旦棉,每隔多長時(shí)間執(zhí)行一次)
// GCD的時(shí)間參數(shù)齿风,一般是納秒 NSEC_PER_SEC(1秒 == 10的9次方納秒)
// 何時(shí)開始執(zhí)行第一個(gè)任務(wù)
// dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC) 比當(dāng)前時(shí)間晚3秒
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);
// 設(shè)置回調(diào)
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"----%@", [NSThread currentThread]);
count++;
//? ? ? ? if (count == 4) {
//? ? ? ? ? ? // 取消定時(shí)器
//? ? ? ? ? ? dispatch_cancel(self.timer);
//? ? ? ? ? ? self.timer = nil;
//? ? ? ? }
});
// 啟動(dòng)定時(shí)器
dispatch_resume(self.timer);
}