iOS开辟- RunLoop

打印 上一主题 下一主题

主题 795|帖子 795|积分 2385

RunLoop用于管理事件的循环处理机制。运行循环在应用步伐的主线程中主动启动,负责监听和分发各种事件,包括用户交互(如触摸事件)、定时器事件、选择器调用和其他异步回调。
运行循环的作用

运行循环的主要作用包括:

  • 处理输入事件:运行循环监听用户的输入,如触摸、点击和滑动事件,并将它们分发到适当的处理步伐。
  • 调度定时器:运行循环管理定时器(NSTimer)的执行,确保在指定的时间触发事件。
  • 执行选择器调用:通过 performSelector:withObject:afterDelay: 等方法安排的选择器调用会在运行循环中执行。
  • 管理异步任务:运行循环与异步API协作,如网络哀求,处理完成后的回调。
  • 保持线程活跃:运行循环使得主线程在没有工作时处于休眠状态,有工作时醒来处理,有用地管理CPU资源。
运行循环的构成

运行循环由以下几个核心组件构成:

  • 输入源(Input Sources):非基于端口的输入源(如用户交互事件)和基于端口的输入源(用于线程或进程间通信)。
  • 定时源(Timer Sources):定时器事件,可以在指定的时间点触发。
  • 运行循环模式(Run Loop Modes):运行循环可以设置为不同的模式,每种模式定义了运行循环在该模式下可以处理的输入源和定时器。这允许运行循环根据当前的活动调解其行为。
观察者

Observers(观察者)是一种监听RunLoop不同活动阶段的机制。是CFRunLoopObserver对象,可以被添加到RunLoop中,以便在RunLoop到达特定的运行阶段时吸收关照。
CFRunLoopObserver可以关注以下几种RunLoop活动(事件):

  • kCFRunLoopEntry:进入RunLoop时触发。
  • kCFRunLoopBeforeTimers:RunLoop处理定时器之前触发。
  • kCFRunLoopBeforeSources:RunLoop处理输入源之前触发。
  • kCFRunLoopBeforeWaiting:RunLoop进入休眠等待输入源之前触发。
  • kCFRunLoopAfterWaiting:RunLoop被唤醒后,处理完唤醒事件之前触发。
  • kCFRunLoopExit:退出RunLoop时触发。
开辟可以创建Observers并指定它们关注的活动,以及一个回调函数,当RunLoop到达这些活动时,回调函数将被调用。
创建和添加Observer的示例代码如下:
  1. CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
  2.     // 在RunLoop即将休眠前执行的代码
  3.     NSLog(@"RunLoop is about to sleep.");
  4. });
  5. CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
复制代码
在这个例子中创建了一个Observer,它会在RunLoop即将休眠前触发。利用CFRunLoopObserverCreateWithHandler函数来创建Observer,并提供了一个block作为回调函数。然后利用CFRunLoopAddObserver将Observer添加到当前的RunLoop中。
利用Observers可以更精细地控制代码的执行机遇。然而,大多数情况下,不需要直接利用Observers,因为高级API(如NSTimer、performSelector:withObject:afterDelay:等)已经足够满足常见的需求。
RunLoop的运行逻辑

RunLoop的运行逻辑可以分解为以下步调:

  • 进入Loop:当RunLoop开始时,它会关照所有注册的Observers(观察者)一个即将进入循环的事件。
  • 处理Timers:RunLoop会关照Observers它即将处理定时器(Timers)。
  • 处理Sources:RunLoop关照Observers它即将处理输入源(Sources)。输入源可以分为两种:Source0和Source1。Source0只包罗应用步伐内部事件,如UI事件;Source1包罗系统内核和其他线程的事件。
  • 处理Blocks:如果有block被添加到RunLoop中,这些block会在这个阶段执行。
  • 处理Source0:RunLoop处理Source0事件,这可能会导致更多的block被执行。
  • 查抄Source1:如果存在Source1事件,RunLoop会直接跳到第8步。
  • 休眠:如果没有立刻要处理的事件,RunLoop会关照Observers它即将休眠,并等待新的事件唤醒。
  • 被唤醒:当RunLoop被事件唤醒时,它会关照Observers,并处理事件。这可能包括处理定时器、处理GCD异步派发到主队列的任务或处理Source1事件。
  • 再次处理Blocks:处理完事件后,RunLoop会再次执行步调4中的block。
  • 决定如何操作:根据前面的执行结果,RunLoop会决定是继承循环照旧退出。如果处理了事件而且还有更多的工作要做,它会回到步调2;如果没有更多的工作大概吸收到退出指令,它会准备退出。
  • 退出Loop:在RunLoop退出前,它会关照所有Observers一个即将退出循环的事件。
RunLoop的其他注意事项


  • 主线程的RunLoop在应用步伐启动时已经被主动创建和启动,因为主线程负责处理UI事件和其他用户交互。
  • 子线程的RunLoop默认不会启动,需要手动管理。如果在子线程中需要长时间运行的任务,而且需要处理事件,可能需要手动启动RunLoop。
  • RunLoop与线程是一一对应的,它在第一次获取时创建,在线程结束时销毁。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王海鱼

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表