每一個線程(包含主線程)都有一個Runloop。對於每個Runloop,系統會隱式建立一個Autorelease pool,這樣全部的release pool會構成一個像callstack同樣的一個棧式結構,在每個Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裏的每一個Object會被release。git
總的說來,Run loop,正如其名,loop表示某種循環,和run放在一塊兒就表示一直在運行着的循環。實際上,run loop和線程是緊密相連的,能夠這樣說run loop是爲了線程而生,沒有線程,它就沒有存在的必要。Run loops是線程的基礎架構部分, Cocoa 和 CoreFundation 都提供了 run loop 對象方便配置和管理線程的 run loop (如下都以 Cocoa 爲例)。每一個線程,包括程序的主線程( main thread )都有與之相應的 run loop 對象。 runloop 和線程的關係:github
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
重點是UIApplicationMain()函數,這個方法會爲main thread設置一個NSRunLoop對象,這就解釋了:爲何咱們的應用能夠在無人操做的時候休息,須要讓它幹活的時候又能立馬響應架構
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
參考連接:《Objective-C之run loop詳解》函數
model 主要是用來指定事件在運行循環中的優先級的,分爲:oop
蘋果公開提供的 Mode 有兩個:ui
RunLoop只能運行在一種mode下,若是要換mode,當前的loop也須要停下重啓成新的。利用這個機制,ScrollView滾動過程當中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動:只能在NSDefaultRunLoopMode模式下處理的事件會影響scrllView的滑動。.net
若是咱們把一個NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運行循環中的時候, ScrollView滾動過程當中會由於mode的切換,而致使NSTimer將再也不被調度。線程
同時由於mode仍是可定製的,因此:code
Timer計時會被scrollView的滑動影響的問題能夠經過將timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)來解決。代碼以下:對象
// // http://weibo.com/luohanchenyilong/ (微博@iOS程序犭袁) // https://github.com/ChenYilong //將timer添加到NSDefaultRunLoopMode中 [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; //而後再添加到NSRunLoopCommonModes裏 NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
通常來說,一個線程一次只能執行一個任務,執行完成後線程就會退出。若是咱們須要一個機制,讓線程能隨時處理事件但並不退出,一般的代碼邏輯 是這樣的:
function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit); }
或使用僞代碼來展現下:
// // http://weibo.com/luohanchenyilong/ (微博@iOS程序犭袁) // https://github.com/ChenYilong int main(int argc, char * argv[]) { //程序一直運行狀態 while (AppIsRunning) { //睡眠狀態,等待喚醒事件 id whoWakesMe = SleepForWakingUp(); //獲得喚醒事件 id event = GetEvent(whoWakesMe); //開始處理事件 HandleEvent(event); } return 0; }
參考連接: 1. 《深刻理解RunLoop》 1. 摘自博文CFRunLoop,原做者是微博@我就叫Sunny怎麼了
經過 retainCount 的機制來決定對象是否須要釋放。 每次 runloop 的時候,都會檢查對象的 retainCount,若是retainCount 爲 0,說明該對象沒有地方須要繼續使用了,能夠釋放掉了。
分兩種狀況:手動干預釋放時機、系統自動去釋放。