RunLoop用于管理事件的循环处理机制。运行循环在应用程序的主线程中自动启动,负责监听和分发各种事件,包括用户交互(如触摸事件)、定时器事件、选择器调用和其他异步回调。
运行循环的主要作用包括:
NSTimer
)的执行,确保在指定的时间触发事件。performSelector:withObject:afterDelay:
等方法安排的选择器调用会在运行循环中执行。运行循环由以下几个核心组件组成:
Observers(观察者)是一种监听RunLoop不同活动阶段的机制。是CFRunLoopObserver
对象,可以被添加到RunLoop中,以便在RunLoop达到特定的运行阶段时接收通知。
CFRunLoopObserver
可以关注以下几种RunLoop活动(事件):
kCFRunLoopEntry
:进入RunLoop时触发。kCFRunLoopBeforeTimers
:RunLoop处理定时器之前触发。kCFRunLoopBeforeSources
:RunLoop处理输入源之前触发。kCFRunLoopBeforeWaiting
:RunLoop进入休眠等待输入源之前触发。kCFRunLoopAfterWaiting
:RunLoop被唤醒后,处理完唤醒事件之前触发。kCFRunLoopExit
:退出RunLoop时触发。开发可以创建Observers并指定它们关注的活动,以及一个回调函数,当RunLoop达到这些活动时,回调函数将被调用。
创建和添加Observer的示例代码如下:
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
// 在RunLoop即将休眠前执行的代码
NSLog(@"RunLoop is about to sleep.");
});
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
在这个例子中创建了一个Observer,它会在RunLoop即将休眠前触发。使用CFRunLoopObserverCreateWithHandler
函数来创建Observer,并提供了一个block作为回调函数。然后使用CFRunLoopAddObserver
将Observer添加到当前的RunLoop中。
使用Observers可以更精细地控制代码的执行时机。然而,大多数情况下,不需要直接使用Observers,因为高级API(如NSTimer
、performSelector:withObject:afterDelay:
等)已经足够满足常见的需求。
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一个即将退出循环的事件。
参与评论
手机查看
返回顶部