每一个线程(包含主线程)都有一个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,说明该对象没有地方须要继续使用了,能够释放掉了。
分两种状况:手动干预释放时机、系统自动去释放。