Runloop的概念
runloop是通过内部维护的事件循环来对事件/消息进行管理的一个对象。
1、没有消息/事件需要处理时,就进入休眠状态,节省资源,由用户状态切换到内核状态。
2、若有消息/事件需要处理时,立刻被唤醒,由内核状态切换到用户状态
为什么Main函数不会退出,就是因为UIApplicationMain内部默认开启了一个runloop,并且执行了一段无限循环的代码,注意这里的无限循环,不是简单的for或者while循环,因为一直在无限循环里,所以这个函数永远不会被返回,而是不断的接收消息/事件以及等待休眠,所以程序运行之后会保持运行状态不会退出
Runloop的数据结构
NSRunloop(Foundation框架)是基于CFRunloop(CoreFoundation框架)的封装,提供了面向对象的封装。
runloop相关的主要有以下5个类
CFRunloop:runloop对象
CFRunloopMode:运行模式
CFRunloopSource:事件/输入源
CFRunloopTimer:定时源
CFRunloopObserver:观察者
Runloop和线程
线程和runloop是一一对应的,其映射关系是保存在全局的NSDictionary里的,自己创建的线程默认是没有开启runloop的,只有当你第一次调用 [NSRunLoop currentRunLoop]时,会创建一个runloop
怎样创建一个常驻线程
主线程是默认开启runloop并且不会释放掉的。
1、为当前线程创建一个runloop
2、向runloop中添加Port/Source等维持RunLoop的事件循环(注意:如果runloop的mode中一个item都没有,runloop会退出的)
3、启动该runloop
怎样保证子线程数据回来时刷新主线程UI的时候不打断用户的滑动操作?
当我们在子请求数据的同时滑动浏览当前页面,如果数据请求成功要切回主线程更新UI,那么就会影响当前正在滑动的体验。
那么我们就可以把刷新的操作放在主线程RunLoop的NSDefaultRunLoop的模式上即可,这样就会等用户不在滑动,并且手指离开的时候执行刷新操作了
主线程RunLoop由UITrackingRunLoopMode
切换到NSDefaultRunLoopMode
时再去更新UI
主线程RunLoop由UITrackingRunLoopMode切换到NSDefaultRunLoopMode时再去更新UI
[self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO modes:@[NSDefaultRunLoopMode]];