Runloop是ios應用於線程中的一種循環機制。系統本身沒有創建runloop的API,不過可以通過currentRunLoop獲取當前RunLoop;主線本身就存在一個runloop,而且是運行轉態,子線程的runLoop需要手動開啓;RunLoop隨着所在線程的結束而被釋放。
實例應用
/* 獲取/創建RunLoop對象 */
[NSRunLoop currentRunLoop];//當前線程的runLoop
[NSRunLoop mainRunLoop];//主線程runLoop
CFRunLoopGetCurrent();
CFRunLoopGetMain();
[NSRunLoop currentRunLoop].getCFRunLoop; //NSRunLoop轉CFRunLoopRef
備註:NSRunLoop對象不是線程安全,如果在不同線程使用同一個runLoop對象,可以用CFRunLoopRef,保證線程安全。
/* 添加定時器及輸入源 */
[[NSRunLoop currentRunLoop] addTimer:<#(nonnull NSTimer *)#> forMode:<#(nonnull NSRunLoopMode)#>]
CFRunLoopAddTimer(<#CFRunLoopRef rl#>, <#CFRunLoopTimerRef timer#>, <#CFRunLoopMode mode#>)
CFRunLoopAddSource(<#CFRunLoopRef rl#>, <#CFRunLoopSourceRef source#>, <#CFRunLoopMode mode#>)
/* 啓動RunLoop */
[[NSRunLoop currentRunLoop] run]; //無條件且以默認的NSDefaultRunLoopMode啓動
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate new]]; //指定過期時間且以默認的NSDefaultRunLoopMode啓動
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate new]];//指定過期時間,指定啓動方式
CFRunLoopRun(); //子線程的runLoop需要啓動
CFRunLoopRunInMode(<#CFRunLoopMode mode#>, <#CFTimeInterval seconds#>, <#Boolean returnAfterSourceHandled#>)
/* 退出RunLoop */
給RunLoop設置超時時間;
CFRunLoopStop([NSRunLoop currentRunLoop].getCFRunLoop); //通知RunLoop停止
/* 主線程場景 */
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fireDemo) userInfo:nil repeats:YES];
可直接使用timer,默認爲NSDefaultRunLoopMode
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
設置爲NSRunLoopCommonModes,防止頁面交互導致暫停
/* 子線程場景 */
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fireDemo) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run]; //run時必須有相應的timer或source
備註:一旦調用這個方法開啓子線程的運行循環就不能停止,阻塞代碼執行,子線程也不會被釋放,除非從始至終都需要開着,其他情況下不建議使用(如:socket source)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];
備註:在run之後會阻塞代碼,等待runLoop結束後纔會執行
/* 阻塞代碼但不阻塞線程 */
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
備註:遇到過子線程NSDefaultRunLoopMode無效,NSRunLoopCommonModes有效的情況,具體原因不詳,可能是由於執行了某個模塊代碼導致NSDefaultRunLoopMode失效了