RunLoop 從表面意思來看運(yùn)行循環(huán)的意思,其實(shí)質(zhì)上也真的很像循環(huán)。其實(shí)在OC中 RunLoop是用來管理線程的。每一個(gè)線程都有一個(gè)RunLoop對(duì)象。可以通過具體的方法去獲得。
盡管RunLoop在開發(fā)中我們一直在用,但是沒有注意他。要想理解RunLoop,首先我們需要先了解一下程序運(yùn)行機(jī)制。
程序運(yùn)行機(jī)制:我們都知道OC是運(yùn)行時(shí)語(yǔ)言,也就是說對(duì)象的類型是在程序運(yùn)行的時(shí)候確定的,調(diào)用類與對(duì)象相應(yīng)的方法。但是最終代碼的執(zhí)行始終是面向過程的。
線程也是一樣:一個(gè)線程從開始代碼執(zhí)行,到結(jié)束代碼銷毀。app如何實(shí)現(xiàn)這樣的機(jī)制:app從運(yùn)行開始一直處于待命狀態(tài),接收到事件之后執(zhí)行操作,操作完成后繼續(xù)等待相應(yīng),直到程序終止運(yùn)行。這樣的管理線程執(zhí)行任務(wù)的機(jī)制就是RunLoop機(jī)制。線程在執(zhí)行中的休眠和激活就是由RunLoop對(duì)象進(jìn)行管理的。
雖然每一個(gè)線程都可以獲取RUnLoop對(duì)象,但是并不是每一個(gè)線程中都有實(shí)例對(duì)象,我們可以這樣理解:如果我們不獲取RunLoop,這個(gè)RunLoop就不存在,我們獲取時(shí),如果不存在,就會(huì)去創(chuàng)建。在主線程中,這個(gè)MainRunLoop是默認(rèn)創(chuàng)建并運(yùn)行激活的。
一般來說獲取runloop的方法有
1、獲取主線程的NSRunLoop
//獲取主線程的NSRunLoop
+(NSRunLoop *)mainRunLoop;
2、獲取當(dāng)前線程的NSRunLoop
//獲取當(dāng)前線程的RunLoop:有的話就直接獲取,沒有的話就自動(dòng)創(chuàng)建
+(NSRunLoop *)currentRunLoop;
NSRunLoop* loop1=[NSRunLoop mainRunLoop];
NSLog(@"1---%@",loop1);
NSRunLoop* loop2=[NSRunLoop currentRunLoop];
NSLog(@"2---%@",loop2);
//打印結(jié)果如下 內(nèi)容比較多 只截取部分
1---{wakeup port = 0x1e03, stopped = false, ignoreWakeUps = false, current mode = UIInitializationRunLoopMode,common modes ={type = mutable set, count = 2,entries =>0 :{contents = "UITrackingRunLoopMode"}2 :{contents = "kCFRunLoopDefaultMode"}},common mode items ={type = mutable set, count = 15,
entries =>........
獲取RunLoop的CFRunLoopRef對(duì)象
-(CFRunLoopREF)getCFRunLoop;
NSRunLoop* loop1=[NSRunLoop mainRunLoop];
NSLog(@"1---%@",loop1);
[loop1 getCFRunLoop];
NSLog(@"ref---%@",[loop1 getCFRunLoop]);
結(jié)果如下
ref---{wakeup port = 0x1e03, stopped = false, ignoreWakeUps = false, current mode = UIInitializationRunLoopMode,common modes ={type = mutable set, count = 2,entries =>0 :{contents = "UITrackingRunLoopMode"}2 :{contents =
將定時(shí)器添加到RunLoop中
-(void)loopTest
{NSRunLoop* loop1=[NSRunLoop mainRunLoop];
NSLog(@"1---%@",loop1);
[loop1 getCFRunLoop];
NSLog(@"ref---%@",[loop1 getCFRunLoop]);
//? ? NSRunLoop* loop2=[NSRunLoop currentRunLoop];
//? ? NSLog(@"2---%@",loop2);
NSTimer* timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(givelog:) userInfo:nil repeats:YES];
[loop1 addTimer:timer forMode:NSDefaultRunLoopMode];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//移除定時(shí)器 不然會(huì)一直執(zhí)行
[timer invalidate];
NSLog(@"1---%@",@"移除成功");
});
}
-(void)givelog:(NSTimer*)time
{
NSLog(@"haha");
}
2017-08-30 15:20:39.533 runtimeTest[6010:148172] haha
2017-08-30 15:20:40.533 runtimeTest[6010:148172] haha
2017-08-30 15:20:41.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:42.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:43.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:44.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:45.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:46.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:47.534 runtimeTest[6010:148172] haha
2017-08-30 15:20:48.533 runtimeTest[6010:148172] haha
2017-08-30 15:20:48.534 runtimeTest[6010:148172] 1---移除成功
某些延遲函數(shù)和選擇器在分線程中的使用,我們必須手動(dòng)開始RunLoop
@interfaceNSObject (NSDelayedPerforming)
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelectorobject:(id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes;
- (void)cancelPerformSelector:(SEL)aSelector target:(id)target argument:(id)arg;
- (void)cancelPerformSelectorsWithTarget:(id)target;