美文网首页
Run Loop 学习

Run Loop 学习

作者: 婉卿容若 | 来源:发表于2017-01-22 15:46 被阅读21次

先码资源(想学 Run Loop 直接看下面博文,不用看我的,我全是引用的):
深入理解 runloop
sunnyxx 线下分享视频
runloop
iOS程序启动与运转- RunLoop个人小结

说明

就是自己阅读笔记,想了解 runloop 可以阅读上面的博客.本文只是个人笔记,留作以后复习,所以只会记下重点(引用自原文).

概念

比较能理解 ibireme 大神的解释

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

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

RunLoop 与线程

线程和 RunLoop 之间是一一对应的,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。

RunLoop.png

获取 RunLoop 方式:

  • CFRunLoopGetMain()
  • CFRunLoopGetCurrent()

RunLoop 对外接口

在 CoreFoundation 里面关于 RunLoop 有5个类:

  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef
RunLoop 关系图.png

说明:

一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个 Source/Timer/Observer。每次调用 RunLoop 的主函数时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode。如果需要切换 Mode,只能退出 Loop,再重新指定一个 Mode 进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。

CFRunLoopSource

Source是RunLoop的数据源抽象类,类似IOS中的protocol
RunLoop定义两个Version的Source
Source0:处理App内部事件,App自己负责管理(触发),如UIEvent,CFSocket
Source1:由RunLoop和内核管理,Mach port驱动 如CFMach、CFMessage

CFRunLoopSourceRef 是事件产生的地方。Source有两个版本:Source0 和 Source1。
• Source0 只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用 CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop,让其处理这个事件。
• Source1 包含了一个 mach_port 和一个回调(函数指针),被用于通过内核和其他线程相互发送消息

CFRunLoopTimerRef

CFRunLoopTimerRef 是基于时间的触发器,它和 NSTimer 是toll-free bridged 的,可以混用。其包含一个时间长度和一个回调(函数指针)。当其加入到 RunLoop 时,RunLoop会注册对应的时间点,当时间点到时,RunLoop会被唤醒以执行那个回调。

CFRunLoopObserverRef

CFRunLoopObserverRef 是观察者,每个 Observer 都包含了一个回调(函数指针),当 RunLoop 的状态发生变化时,观察者就能通过回调接受到这个变化。可以观测的时间点有以下几个:

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
    kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
    kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
    kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
};

上面的 Source/Timer/Observer 被统称为 mode item,一个 item 可以被同时加入多个 mode。但一个 item 被重复加入同一个 mode 时是不会有效果的。如果一个 mode 中一个 item 都没有,则 RunLoop 会直接退出,不进入循环。

RunLoop 的 Mode

CFRunLoopMode 和 CFRunLoop 的结构大致如下:

struct __CFRunLoopMode {
    CFStringRef _name;            // Mode Name, 例如 @"kCFRunLoopDefaultMode"
    CFMutableSetRef _sources0;    // Set
    CFMutableSetRef _sources1;    // Set
    CFMutableArrayRef _observers; // Array
    CFMutableArrayRef _timers;    // Array
    ...
};
 
struct __CFRunLoop {
    CFMutableSetRef _commonModes;     // Set
    CFMutableSetRef _commonModeItems; // Set<Source/Observer/Timer>
    CFRunLoopModeRef _currentMode;    // Current Runloop Mode
    CFMutableSetRef _modes;           // Set
    ...
};

这里有个概念叫 "CommonModes":一个 Mode 可以将自己标记为"Common"属性(通过将其 ModeName 添加到 RunLoop 的 "commonModes" 中)。每当 RunLoop 的内容发生变化时,RunLoop 都会自动将 _commonModeItems 里的 Source/Observer/Timer 同步到具有 "Common" 标记的所有Mode里。

CFRunLoop对外暴露的管理 Mode 接口只有下面2个:

CFRunLoopAddCommonMode(CFRunLoopRef runloop, CFStringRef modeName);
CFRunLoopRunInMode(CFStringRef modeName, ...);

Mode 暴露的管理 mode item 的接口有下面几个:

CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);
CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopRemoveObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);

苹果公开提供的 Mode 有两个:kCFRunLoopDefaultMode (NSDefaultRunLoopMode) 和 UITrackingRunLoopMode,你可以用这两个 Mode Name 来操作其对应的 Mode。

同时苹果还提供了一个操作 Common 标记的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes),你可以用这个字符串来操作 Common Items,或标记一个 Mode 为 "Common"。使用时注意区分这个字符串和其他 mode name。


还不会用,好神伤,还要继续看

相关文章

  • runloop

    走进Run Loop的世界 (一):什么是Run Loop?走进Run Loop的世界 (二):如何配置Run L...

  • Run Loop 学习

    先码资源(想学 Run Loop 直接看下面博文,不用看我的,我全是引用的):深入理解 runloopsunnyx...

  • iOS Runloop学习笔记

    一、** what is run loop ** 1、A run loop is an abstraction t...

  • iOS开发之Run loop

    1.什么是Run loop,Run loop有什么作用? 2.Run loop 是怎么运作的? 3.什么情况下使用...

  • 详解Run Loop

    Run Loop Run Loop是事件驱动的。 iOS中有2套API来访问使用Run LoopFoundatio...

  • iOS Runloop(二)

    Run Loop观察者源是合适的同步或异步事件发生时触发,而run loop观察者则是在run loop本身运行的...

  • python asyncio并发编程(3)

    1. loop.run_forever()与loop.run_until_complete()的区别 (1) l...

  • IOS多线程编程指南二之Runloop

    一、什么是Runloop A run loop is an event processing loop that ...

  • Run Loops基础概念篇二

    When Would You Use a Run Loop? 你唯一要使用run loop,就是当你要在appli...

  • CFRunLoop -- API

    获取 Run Loop 的方法 运行以及停止 Run Loop 的方法 管理 Sources 的方法 管理 Obs...

网友评论

      本文标题:Run Loop 学习

      本文链接:https://www.haomeiwen.com/subject/kxokbttx.html