1字面意思:运行循环、跑圈,内部其实就是do-while循环,在这个循环内部不断地处理各种事物,NSRunloop就是消息循环,每一个线程内部都有一个消息循环,只有主线程的消息循环默认开启,子线程的消息循环默认不开启 ,如果不主动获取Runloop,子线程内部就不会创建RunLoop,生命周期是在第一次获取时创建,在线程结束时销毁,runloop对象是利用字典来进行存储,而且key是对应的线程,value为该线程对应的Runloop.
2运行循环的目的:
a保证应用程序不退出,持续运行,内部是do-while循环,在这个循环内部不断处理各种事件
b处理app中的各种事件(触摸事件、定时器事件、selector事件、选择器performSelector)接受输入事件来自两种不同的来源:输入源和定时源,输入源(键盘,鼠标,NSPort,NSConnection)input source和定时源timer source.
performSelector:onThread:也可以作为输入事件
(NSConnection非常依赖线程里的消息循环)
c没有事件发生,会让程序进入休眠状态,节省CPU资源,提高程序性能
Runloop是程序一直存在并不断处理事件的原因,main函数中的RunLoop,在UIApplication函数内部启动一个Runloop,该函数返回一个int类型的值,默认启动的Runloop是跟主线程相关的
3ios开发中,有两套api访问Runloop,foundation框架(NSRunloop),core foundation框架(CFRunloopRef),都代表Runloop对象,等价的可以互相转换,
4获取Runloop对象,
NSRunLoop *runloop1 = NSRunloop currentRunLoop];
CFRunLoop *runloop2 = CFRunLoopGetCurrent();
获取主Runloop
NSRunLoop *runloop1 = NSRunLoop mainRunLoop];
CFRunLoop *runloop2 = CFRunLoopGetMain();
5基本使用:每次Runloop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode,如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入,这样做的主要目的是为了隔离不同Mode中的Source、Timer、Observer,让其互不影响
消息循环处理输入事件时,必须消息循环的模式和输入源的运行模式相互匹配,输入源对应的事件才能被消息循环检测到.常用的模式有,NSRunloopCommonModes,NSDefaultRunloopModes,UITrackingRunLoopModes
a NSTimer必须添加到runloop中才会工作,且其工作受到runloop运行模式的影响
b runloop启动之后会选择一种运行模式,在执行执行会先检查运行模式内部是否有source和timers,如果一个sourc或者是一个timer都没有那么runlooop启动之后就立刻退出了。
c runlooop的source有两种分类方法
按照以前的分类方法可以分为: 基于端口的 自定义的 performSelector事件
按照函数调用栈来划分: source0 soucrce1
使用:
a 开启NSTimer,控制定时器在特定模式下执行
bPerformSelector OnThread:控制线程执行不同的任务
c自动释放池(可通过Observer监听RunLoop的状态)
第一次创建:进入runloop的时候
最后一次释放:runloop退出的时候
其它创建和释放:当runloop即将休眠的时候会把之前的自动释放池释放,然后重新创建一个新的释放池
d常驻线程:让一个子线程不进入消亡状态,等待其他线程发来消息,处理其他事件
常驻线程实现:
主线程对应的runloop默认已经创建好了,但是子线程对应的runloop需要手动创建
子线程对应的runloop还需要手动的开启,否则该runloop一创建出来就退出;在开启前要先添加事件,否则也会退出。
保证mode里面有事件,不让runloop立刻退出
可以往runloop中添加source和timer,但是添加observer是没有作用的