RunLoop 處理事件源-- performSelector方法

一、RunLoop和線程的關(guān)系

? ? ? ?每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象,一個(gè)線程可以開啟多個(gè)RunLoop,只不過都是嵌套在最大的RunLoop中,其關(guān)系是保存在一個(gè)全局的 Dictionary 里。

二、線程中RunLoop的生命周期

創(chuàng)建:

? ? ?1、主線程:run loop默認(rèn)是啟動(dòng)的,用于接收各種輸入sources

? ? ? 2、子線程:線程剛創(chuàng)建時(shí)并沒有 RunLoop,如果你不主動(dòng)獲取,那它一直都不會(huì)有。

? ? ?在當(dāng)前子線程中調(diào)用[NSRunLoop currentRunLoop]的時(shí)候,如果有就獲取,沒有就創(chuàng)建

啟動(dòng):

? ? ?1、主線程:默認(rèn)是啟動(dòng)的

? ? ?2、子線程:要手動(dòng)添加

獲?。?/p>

? ? ?1、主線程:全局獲取其RunLoop;[NSRunLoop mainRunLoop]或者 CFRunLoopGetMain();

? ? ? 2、子線程:只能在線程的內(nèi)部獲取其RunLoop;[NSRunLoop currentRunLoop]或者CFRunLoopGetCurrent();

銷毀:

? ? 1、主線程:app結(jié)束時(shí)

? ? 2、子線程:子線程結(jié)束

三、在當(dāng)前線程的Run Loop下執(zhí)行指定的 @selector 方法

? ? ?當(dāng)調(diào)用 NSObject的performSelector:onThread:時(shí),實(shí)際上其內(nèi)部會(huì)創(chuàng)建一個(gè) Timer 并添加到當(dāng)前線程的 RunLoop 中:

打印一下看看:

其實(shí)是加在runloop中

看以下的代碼:

- (void)viewDidLoad {

? ? ?[super viewDidLoad];

? ? ?NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(nslogHi) object:nil];

? ? ?[thread start];

? ? ?[self performSelector:@selector(nslogHello) onThread:thread withObject:nil waitUntilDone:NO];

? ? NSLog(@"_end");

}

- (void)nslogHi {

? ? ? NSLog(@"hi....");

}

- (void)nslogHello {

? ? ? NSLog(@"hello.....");

}

最會(huì)輸出:

? ? ?2015-09-28 14:09:15.650 PCRunLoopThread[74414:5556013] hi....

? ? ?2015-09-28 14:09:15.650 PCRunLoopThread[74414:5555961] _end

結(jié)論:

? ? ? 1、線程在執(zhí)行后會(huì)退出當(dāng)前的RunLoop,也就是RunLoop會(huì)在一個(gè)線程結(jié)束時(shí)一同銷毀。

? ? ? 2、如果當(dāng)前線程沒有RunLoop的話,performSelector:onThread的方法也就失效。

==================================================

那么我們要想要把hello.....打印出來!!要怎么辦呢?

就線程一直運(yùn)行或者暫時(shí)阻塞一下線程:

1、向創(chuàng)建的RunLoop添加NSPort(Sources),讓Mode不為空,RunLoop能進(jìn)入循環(huán)不會(huì)退出

? ? ? [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];

? ? ? [[NSRunLoop currentRunLoop] run];

見代碼:

- (void)nslogHi {

? ? ? [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];

? ? ? [[NSRunLoop currentRunLoop] run];

? ? ?NSLog(@"hi....");

}

使用run啟動(dòng)線程,是不會(huì)退出,所以也就打印不出hi....

2、讓RunLoop一直嘗試運(yùn)行,判斷Mode是否為空,不是為空就進(jìn)入RunLoop循環(huán)

? ? ? ?[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]

見代碼:

- (void)nslogHi {

? ? ?while (!_isNewThreadAborted) {

? ? ? ? ? ? ?BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode

? ? ? ? ? ? beforeDate:[NSDate distantFuture]];

? ? ? ? }

? ? ? ? NSLog(@"hi....");

}

具體的demo

網(wǎng)上找了些資料,貼一下的三種手動(dòng)啟動(dòng)runloop的方式:

讓一個(gè)子線程不進(jìn)入消亡狀態(tài),等待其他線程發(fā)來消息,處理其他事件,其實(shí)就是讓線程跑一個(gè)runLoop

1、- (void)run;

運(yùn)行 NSRunLoop,運(yùn)行模式為默認(rèn)的NSDefaultRunLoopMode模式,沒有超時(shí)限制。因?yàn)闊o條件運(yùn)行

不建議使用,因?yàn)檫@個(gè)接口會(huì)導(dǎo)致Run Loop永久性的運(yùn)行在NSDefaultRunLoopMode模式,即使使用CFRunLoopStop(runloopRef);也無法停止Run Loop的運(yùn)行,那么這個(gè)子線程就無法停止,只能永久運(yùn)行下去。

示例:

[[NSRunLoop currentRunLoop] run];

2、[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];

運(yùn)行 NSRunLoop: 參數(shù)為運(yùn)時(shí)間期限,運(yùn)行模式為默認(rèn)的NSDefaultRunLoopMode模式,自己設(shè)置的Run Loop運(yùn)行時(shí)間,超時(shí)就退出

示例:

while (!Done)

{

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate

dateWithTimeIntervalSinceNow:10]];

NSLog(@"exiting runloop.........:");

}

3、- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

mode: ? 指定runloop模式來處理輸入源

limitDate:設(shè)置為NSDate distantFuture,所以除非處理其他輸入源結(jié)束,否則永不退出處理暫停的當(dāng)前處理的流程

return: ? 返回值為YES表示是處理事件后返回的,NO表示是超時(shí)或者停止運(yùn)行導(dǎo)致返回的

這個(gè)接口在非Timer事件觸發(fā)、顯式的用CFRunLoopStop停止Run Loop、到達(dá)limitDate后會(huì)退出返回。

如果僅是Timer事件觸發(fā)并不會(huì)讓Run Loop退出返回;

如果是PerfromSelector***事件或者其他Input Source事件觸發(fā)處理后,Run Loop會(huì)退出返回YES。

示例:

while (!Done)

{

BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode

beforeDate:[NSDate distantFuture]];

NSLog(@"exiting runloop.........: %d", ret);

}

當(dāng)判斷條件為YES時(shí),當(dāng)前runloop會(huì)一直接收處理其他輸入源,當(dāng)前流程不繼續(xù)往下執(zhí)行。

當(dāng)判斷出為A為NO,當(dāng)前流程繼續(xù)往下執(zhí)行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是Run Loops RunLoops是與線程相關(guān)聯(lián)的基礎(chǔ)部分,一個(gè)Run Loop就是事件處理循環(huán),他是用來...
    傻傻小蘿卜閱讀 1,096評(píng)論 0 5
  • 首先看一段AF2.x經(jīng)典代碼: 首先我們要明確一個(gè)概念,線程一般都是一次執(zhí)行完任務(wù),就銷毀了。 而添加了runlo...
    涂耀輝閱讀 22,863評(píng)論 42 293
  • 什么情況下使用runloop? runloop好比就是跑圈,就是一個(gè)線程一直在做某一件事情。 一般主線程會(huì)自動(dòng)運(yùn)行...
    進(jìn)擊的小杰閱讀 4,530評(píng)論 4 7
  • 一、什么是runloop 字面意思是“消息循環(huán)、運(yùn)行循環(huán)”。它不是線程,但它和線程息息相關(guān)。一般來講,一個(gè)線程一次...
    WeiHing閱讀 8,300評(píng)論 11 111
  • Run loop 剖析:Runloop 接收的輸入事件來自兩種不同的源:輸入源(intput source)和定時(shí)...
    Mitchell閱讀 12,629評(píng)論 17 111

友情鏈接更多精彩內(nèi)容