什么是runloop?
运行循环 。 如果没有runloop 程序执行完毕后就会立即退出,如果有程序就会一直运行,且时刻等待用户输入操作。runloop可以在需要时进行,没有操作时休息节省cpu资源,提高程序性能
了解了RunLoop,那么它什么时候开始工作呢?
UIApplicationMain函数内启动了Runloop,程序不会马上退出,而是保持运行状态。因此每一个应用必须要有一个runloop, 我们知道主线程一开起来,就会跑一个和主线程对应的RunLoop,那么RunLoop一定是在程序的入口main函数中开启
RunLoop 内部 由 do while判断进行类似于死循环所以可以保证程序一直进行
RunLoop的作用
1 保持程序的持续运行 程序一启动就会开一个主线程,就会相应的跑一个runloop来保证主线程不会被销毁,也保证了程序的持续运行 2 处理App的各种事件 比如触摸,selector,定时器 3 节省cpu资源,提高程序性能
RunLoop和线程间的关系
1 每条线程都有唯一的一个与之对应的runloop对象
2 RunLoop保存在一个全局的 Dictionary里,线程作为key,RunLoop作为value
3 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建 RunLoop在第一次获取时创建,在线程结束时销毁
线程和 RunLoop 之间是一一对应的,其关系是保存在一个 Dictionary 里。所以我们创建子线程RunLoop时,只需在子线程中获取当前线程的RunLoop对象即可[NSRunLoop currentRunLoop];如果不获取,那子线程就不会创建与之相关联的RunLoop,并且只能在一个线程的内部获取其 RunLoop [NSRunLoop currentRunLoop];方法调用时,会先看一下字典里有没有存子线程相对用的RunLoop,如果有则直接返回RunLoop,如果没有则会创建一个,并将与之对应的子线程存入字典中。当线程结束时,RunLoop会被销毁
RunLoop 内部实现
RunLoop 结构体看源码可以知道里面有两个比较重要的成员变量
其实是指向__CFRunLoopMode结构体的指针,__CFRunLoopMode结构体,其中有以下成员变量
CFRunLoopModeRef代表RunLoop的运行模式,一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer,而RunLoop启动时只能选择其中一个Mode作为currentMode。
Source0:触摸事件
Source1:基于port的线程间通信
Timer: 定时器,NSTimer
Observer : 监听器,用于监听RunLoop的状态
系统默认的五个model
Mode间的切换
我们肯定遇到过这样的问题 当我们使用NSTimer每一段时间执行一些事情时滑动UIScrollView,NSTimer就会暂停,当我们停止滑动以后,NSTimer又会重新恢复的情况
真正的原因是什么呢?
NSTimer不管用是因为Mode的切换,因为如果我们在主线程使用定时器,此时RunLoop的Mode为kCFRunLoopDefaultMode,即定时器属于kCFRunLoopDefaultMode,那么此时我们滑动ScrollView时,RunLoop的Mode会切换到UITrackingRunLoopMode,因此在主线程的定时器就不在管用了,调用的方法也就不再执行了,当我们停止滑动时,RunLoop的Mode切换回kCFRunLoopDefaultMode,所以NSTimer就又管用了。
还有就是回到主线程加载图片,滑动scrollview 也不加载了,是因为performSelector默认是在default模式下运行,因此在滑动ScrollView时,图片不会加载
网友评论