CFRunLoop概念

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CFRunLoop概念相关的知识,希望对你有一定的参考价值。

概念

一个线程,用来执行一个任务,执行完成后线程就会退出,然而线程的创建和消耗很耗费资源。所以我们需要一个机制,让线程没有任务执行的时候进入睡眠状态,避免资源占用,需要处理任务时线程被唤醒执行任务。通常的代码逻辑是这样的:

function loop() {
  initialize();
  do {
    var message = get_next_message();
    process_message(message);
  }while (message != quit);
}

这种模型被称为Event Loop.比如 Windows 程序的消息循环,比如 OSX/ios 里的 RunLoop。

所以,RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行上面 Event Loop 的逻辑。线程执行了这个函数后,就会一直处于这个函数内部 "接受消息->等待->处理" 的循环中,直到这个循环结束(比如传入 quit 的消息),函数返回。

 

线程与RunLoop的关系

线程与RunLoop之前一一对应。其关系保存在一个字典中,key是phread_t,value是CFRunLoopRef。线程刚创建时是没有RunLoop的,当你第一次获取线程对应的RunLoop时,RunLoop对象被创建。RunLoop的销毁是发生在线程结束时。

 

RunLoop的mode

kCFRunLoopDefaultMode: App平时所处的状态。

TrackingRunLoopMode: 追踪ScrollView滑动时所处的状态。

kCFRunLoopCommonModes:加入到这个mode中的ource/Observer/Timer ,每当RunLoop发生变化时,RunLoop 都会自动将 _commonModeItems 里的 Source/Observer/Timer 同步到具有 "Common" 标记的所有Mode里。

例子:

问题描述:当我在tableView中使用定时器时,加入一个时间倒计时,每1秒更新时间,但是发现定时器的执行非常不准。

原因:当我们滑动tableView时,RunLoop会切换到TrackingRunLoopMode模式,由于定时器默认是加在DefaultMode模式下,所以在TrackingRunLoopMode下不会执行定时器的响应,定时器事件被阻塞,当滑动结束时切换回DefaultMode,执行定时器之前被阻塞的事件,导致时间倒计时不到1秒就被更新。

解决方法: [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];将定时器加入到RunLoop的CoomonModes下

 

参考:http://blog.ibireme.com/2015/05/18/runloop/

 

以上是关于CFRunLoop概念的主要内容,如果未能解决你的问题,请参考以下文章

CFRunLoop源码分析笔记

CFRunLoop源码分析笔记

iOS之深入解析CFRunloop的多线程隐患

__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 18 23 CoreFoundation 崩溃

runloop 和 CFRunLoop - 定时器 - NSTimer 和 GCD定时器

深入理解run loop