Runloop 学习之 CFRunloopObserver

本文详细介绍了CFRunloopObserver的定义、功能及其在AutoreleasePool、UI绘制和手势识别中的应用。它允许观察runloop的六个不同状态,并在特定时刻触发回调,如在即将进入runloop时创建自动释放池,即将进入睡眠时处理UI更新和手势识别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CFRunloopObserver

CFRunloopObserver 定义
struct __CFRunloopObserver {
	CFRuntimeBase _base;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop;
    CFIndex _rlCount;
    CFOptionFlags _activities;      /* immutable */
    CFIndex _order;         /* immutable */
    CFRunLoopObserverCallBack _callout; /* immutable */
    CFRunLoopObserverContext _context;  /* immutable, except invalidation */
};

结论:
1. 一个 observer 只能观察一个 runloop
2. 一个 observer 可以观察多个 runloop 状态

CFRunloopObserver 功能

CFRunloopObserver 观察 runloop 的各种状态,并抛出回调。

runloop 有6种状态

  • 即将进入 runloop
  • 即将处理 timer
  • 即将处理 source
  • 即将进入睡眠
  • 即将唤醒(X) (被唤醒但是还没开始处理事件)
  • 即将退出 runloop(X)(runloop已经退出)
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0), //即将进入run loop
    kCFRunLoopBeforeTimers = (1UL << 1), //即将处理timer
    kCFRunLoopBeforeSources = (1UL << 2),//即将处理source
    kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠
    kCFRunLoopAfterWaiting = (1UL << 6),//被唤醒但是还没开始处理事件
    kCFRunLoopExit = (1UL << 7),//run loop已经退出
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};
CFRunloopObserver 应用
  • AutoreleasePool
    应用启动后,程序会注册两个 Observer 观察:_wrapRunLoopWithAutoreleasePoolHandler

    1. 即将进入 runloop(调用 objc_autoreleasePoolPush() 为当前 page 添加哨兵对象)
    2. 即将进入睡眠(先调用 objc_autoreleasePoolPop() release autorelease 对象,再调用 objc_autoreleasePoolPush() 为当前 page 添加新的哨兵对象),退出 runloop(调用 objc_autoreleasePoolPop() 释放自动释放池)。
  • UI绘制
    应用启动后,程序会注册一个 Observer 观察:_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv

    1. 即将进入睡眠。当 views 的 frame 发生改变,或视图的层级发生变化时等,这些 view 会被标记为待处理,并被加入到一个全局的容器中,当 runloop 即将进入睡眠时,回调这个 observer 回调,查找有没有需要更新的 views,若有则进行绘制。(所以当 view.frame 发生变化时,会在下一个 runloop 周期内绘制)
  • 手势识别
    苹果注册了一个 observer 观察:_UIGestureRecognizerUpdateObserver()

    1. 即将进入睡眠。当用户触摸屏幕时,首先 IOKit.framework 会产生一个 IOHIDEvent 事件,并由 springboard 接收。springboard 通过 mach port 转发给应用进程,触发 runloop 的 source1 回调,并调用 _UIApplicationHandleEventQueue() 进行应用内部分发。_UIApplicationHandleEventQueue() 若识别这是一个手势,首先会调用 cancel 将当前的 touchesBegin/Move/End 回调打断。随后系统将对应的 UIGestureRecognize 标记为待处理。runloop 即将进入睡眠时,获取所有待处理的 gesture,并执行其回调。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值