NSRunLoop--NSRunLoop是IOS消息機(jī)制的處理模式,控制NSRunLoop里面線程的執(zhí)行和休眠领铐,在有事情做的時候使當(dāng)前NSRunLoop控制的線程工作,沒有事情做讓當(dāng)前NSRunLoop的控制的線程休眠宋舷。
如果說整個工廠是一條進(jìn)程,里面的線程是生產(chǎn)線祝蝠,那么runloop就是守著這些生產(chǎn)線的工人汹来,在生產(chǎn)線不做的情況下進(jìn)行暫停休眠改艇,使線程不會被釋放掉收班,而且在runloop的管理下谒兄,內(nèi)存消耗也是極少的摔桦。
NSRunLoop 就是一直在循環(huán)檢測承疲,從線程start到線程end,檢測inputsource(如點擊燕鸽,雙擊等操作)同步事件兄世,檢測timesource同步事件啊研,檢測到輸入源會執(zhí)行處理函數(shù),首先會產(chǎn)生通知党远,corefunction向線程添加runloop observers來監(jiān)聽事件削解,意在監(jiān)聽事件發(fā)生時來做處理沟娱。 它是一個集合,包括監(jiān)聽:事件源济似,定時器矫废,以及需通知的runloop observers
上面是runloop的生命周期砰蠢,在loop休眠狀態(tài)下,他會將前面添加的資源放入線程池進(jìn)行自動釋放娩脾,然后開啟,再不斷重復(fù)柿赊。
由定時器例子來說明,模式具體分為三種
NSTimer*timer = [NSTimertimerWithTimeInterval:2.0target:selfselector:@selector(run)userInfo:nilrepeats:YES];
//定時器只運行在NSDefaultRunLoopMode下碰声,一旦RunLoop進(jìn)入其他模式诡蜓,這個定時器就不會工作,該模式表示在沒有輸入源的情況下
//? ? [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
//定時器只運行在UITrackingRunLoopMode下胰挑,一旦RunLoop進(jìn)入其他模式椿肩,這個定時器就不會工作,有輸入源的情況下
//? ? [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
//定時器會跑在標(biāo)記為common modes的模式下郑象,以上兩種通用,像廣告輪播等就會用到該模式厂榛。
//標(biāo)記為common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode
[[NSRunLoopcurrentRunLoop]addTimer:timerforMode:NSRunLoopCommonModes];
而如果是直接調(diào)用
NSTimer*timer = [NSTimerscheduledTimerWithTimeInterval:2.0target:selfselector:@selector(run)userInfo:nilrepeats:YES];
則系統(tǒng)已經(jīng)自動被添加到當(dāng)前runLoop中丽惭,而且是NSDefaultRunLoopMode击奶,可進(jìn)行修改
//修改模式
[[NSRunLoopcurrentRunLoop]addTimer:timerforMode:NSRunLoopCommonModes];
那么一般來說责掏,當(dāng)你開啟子線程柜砾,完成方法之后换衬,子線程必然被銷毀痰驱,哪怕你使用指針也沒用冗疮,將會導(dǎo)致carsh,而在這樣的情況下,如果打算使該線程繼續(xù)執(zhí)行术幔,則需要開啟runloop,并添加對應(yīng)的port(輸入源等)诅挑,具體例子如下
- (void)viewDidLoad {
[superviewDidLoad];
self.thread= [[NSThreadalloc]initWithTarget:selfselector:@selector(execute)object:nil];
[self.threadstart];
}
// 方法一泛源,無限循環(huán)并開啟runloop,在該狀態(tài)下如果線程沒有事先開啟拔妥,沒有給runloop傳遞source达箍,那么runloop在run的過程中會先檢測是否有資源没龙,沒有就釋放缎玫,將會不斷輸出測試語句硬纤,直到線程開啟赃磨,runloop接受到資源,runloop就會不斷檢測邻辉,開始管理子線程腮鞍。
- (void)execute
{
while(1) {
[[NSRunLoopcurrentRunLoop]run];
nslog@“測試測試-------”;
}
}
// 方法二
- (void)execute
{
// ?開啟時需要添加port監(jiān)聽
//? ? [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
//? ? [[NSRunLoop currentRunLoop] run];
}
最后說一下另一種情況莹菱,如果在子線程內(nèi)開啟定時器
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
前面說過移国,這種方法默認(rèn)已經(jīng)添加了NSDefaultRunLoopMode模式的runloop 道伟,但是子線程方法內(nèi)還是不會執(zhí)行迹缀,因為沒有run起來皱卓,所以還要添加一行代碼
[[NSRunLoop currentRunLoop] run];
當(dāng)然裹芝,如果在主線程內(nèi)執(zhí)行定時器娜汁,自然可以省略該步驟。