您的位置:首页 > 移动开发 > IOS开发

iOS RunLoop

2016-03-21 10:45 507 查看
什么是RunLoop?RunLoop到底有多神秘,多神奇, RunLoop是怎么工作的,有什么用,今天就来带大家简略的刨根问底一下。
当一个App启动,如果我们不做任何交互操作,那么App默认不会做任何响应,一旦我们触摸了屏幕,或点击了某个按钮,程序就立即做出相应的响应,给我们的操作一个反馈。
仿佛这个app是处于一个时刻准备着的状态,没人干活的时候就休息,有人操作了就做出响应,这一切终究归于一个叫RunLoop的东西。Run -> 运行,Loop -> 循环,RunLoop就是一个运行循环。那什么才是运行循环呢?在iOS中RunLoop又充当一个什么样的角色呢?
其实在App中,所有的事件响应都由运行循环来派发和调度,当用户没有任何操作时,运行循环处于休眠状态,一旦用户点击了,或者触摸了屏幕某个地方,运行循环会立即苏醒,来找到最佳响应者(这里涉及到响应者链条,后续会继续说明),然后处理这个事件。

优点:
因为有了运行循环的存才,不需要app一直除以活跃状态,一切由RunLoop来监管,这样大大节省了系统资源。

RunLoop与线程的关系:
程序启动会后,会执行main方法,设置AppDelegate,并且会为主线程设置RunLoop并默认启动,这就是为什么程序启动,就能响应操作的原因。

而当我们开启子线程的时候,子线程的运行循环默认不开启,这是因为除了主线程以外,并不是线程开的越多越好,当子线程工作完成,出于一个空闲状态时,这个线程会被底层线程池回收,而如果子线程的RunLoop默认是开启的,那么这个子线程永远释放不掉,反而导致性能下降,所以,为什么主线程的运行循环默认启动,而子线程的运行循环默认不启动,大家应该能够了解了。

RunLoop内部:挂一张任何帖子都看得到的图



RunLoop内部有一个输入源(input sources),一个定时源(Timer sources)
1. 输入源:传递异步事件,消息通常来自与其他线程,处理其他线程的消息,比如:下载操作执行完毕,要回到主线程个更新UI,这些异步事件,就是有RunLoop来监听和管理
2. 定时源:传递同步事件,发生在特定时间,或者时间间隔,比如:定时检查UI界面上有没有刷新事件,点击时间等等,也就是处理本线程上的事件

运行循环共有5总模式:
1. NSDefaultRunLoopMode:是RunLoop默认的模式,表示程序空闲。如果我们用NSTimer来每个一秒钟打印输出的时候,一旦有手势操作(例如滑动,滚动操作),那么NSTimer就会停止打印。所以这是RunLoop默认的模式。

2. UITrackingRunLoopMode:跟踪模式(是ScrollView专用的模式),上面第一条所说的,一旦有滚动,滑动类似的操作,RunLoop就会默认由NSDefaultRunLoopMode模式切换到UITrackingRunLoopMode模式,目的就是为了保证滑动的流畅性,给用户提供流畅的体验。

3. NSRunLoopCommonMode:这种模式会包含以上两种模式,我们滑动操作的同时,NSTimer时钟调用的方法也会被执行(也会打印出来结果),但是,一旦所调用的方法中,有耗时操作,当我们再次滑动时,效果简直卡到爆。
所以,再实际开发中,不建议讲RunLoop的模式更改为NSRunLoopCommonMode。
但是,有的需求就是又要做耗时操作,又想有流畅滑动效果,那么OK,将耗时操作放在后台,将时钟操作放在子线程(注意:子线程RunLoop需要手动开启:CFRunLoopRun(),CFRunLoopStop(CFRunLoopCurrent())停止运行循环);

4. UIInitializationRunLoopMode:在程序刚刚启动时进入的第一个模式,启动完成就不再使用。

5. GSEventReceiveRunLoopMode:接收系统事件的内部mode,通常用不到。

RunLoop应用场景:
1. 滑动与刷新
2. 常驻子线程
保持子线程长期运转而不被销毁,可以在子线程手动开启RunLoop
3. NSURLConnection的下载
NSURLConnection的下载操作默认是在主线程的(所有早就了ASI与AFN框架,iOS主推NSURLSession),为了不影响主线程UI操作,将下载任务放在子线程,就需要手动开启RunLoop
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RunLoop iOS runloop