加入收藏 | 设为首页 | 会员中心 | 我要投稿 汽车网 (https://www.0577qiche.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

iOS - RunLoop总结 by:nixs

发布时间:2023-04-04 11:13:50 所属栏目:教程 来源:
导读:详细示例代码github仓库总结:NIiOS

##### (二十) iOS RunLoop
```
Runloop
RunLoop的应用
- [x] 常驻线程
NSTimer
- [x] 1. 定时器的使用
- [x] 2. 滑动时失
详细示例代码github仓库总结:NIiOS

##### (二十) iOS RunLoop
```
Runloop
    RunLoop的应用
        - [x] 常驻线程
        NSTimer
            - [x] 1. 定时器的使用
            - [x] 2. 滑动时失效
            - [x] 3. 不准时
        - [x] AutoreleasePool
        - [x] 事件响应
        - [x] 手势识别
        - [x] 界面更新
        PerformSelecter
            // 1.和RunLoop不相干,底层直接调用objc_sendMsg方法
                - [x] (id)performSelector:(SEL)aSelector withObject:(id)object;
            // 2. 和RunLoop相关,封装成Source0事件,依赖于RunLoop,若线程无对应的RunLoop,会调用objc_sendMsg执行
                - [x] (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
            // 3. 和RunLoop相关,封装成Timers事件
                - [x] (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
        关于 GCD
            - [x] 在 RunLoop 的源代码中可以看到用到了 GCD 的相关内容,但是 RunLoop 本身和 GCD 并没有直接的关系。
    RunLoop中的Mode
        - [x] 一个RunLoop包含若干个Mode,每个Mode又包含若干个 Source/Timer/Observer。这句话真的是点晴之笔,一句话就把5个相关类的关系说的一清二楚。
        - [x] 一个CFRunLoopModeRef对象有一个name,若干source0,source1,timer,observer和port,可以看出事件都是由mode在管理,而RunLoop管理着Mode。
        __CFRunLoopMode的五种运行模式(系统默认注册的五个Mode)
            - [x] 1. kcfRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
            - [x] 2. UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
            - [x] 3. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用,会切换到kcfRunLoopDefaultMode
            - [x] 4. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
            - [x] 5. kcfRunLoopCommonModes: 这是一个占位用的Mode,作为标记kcfRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一种真正的Mode 
        CFRunLoopSourceRef
            - [x] Source0 只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用 CFRunLoopSourceSignal (source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp (runloop) 来唤醒 RunLoop,让其处理这个事件。
            - [x] Source1 包含了一个 mach_port 和一个回调(函数指针),被用于通过内核和其他线程相互发送消息。这种Source 能主动唤醒 RunLoop 的线程,其原理在下面会讲到。
        CFRunLoopTimerRef
            - [x] 是基于时间的触发器
            - [x] CFRunLoopTimerRef 是基于时间的触发器,它和 NSTimer 是 toll-free bridged 的,可以混用。其包含一个时间长度和一个回调(函数指针)。当其加入到 RunLoop 时,RunLoop 会注册对应的时间点,当时间点到时,RunLoop 会被唤醒以执行那个回调。
        CFRunLoopObserverRef
            - [x] CFRunLoopObserverRef 是观察者,每个 Observer 都包含了一个回调(函数指针),当 RunLoop 的状态发生变化时,观察者就能通过回调接受到这个变化。
    RunLoop的相关类之间关系
        RunLoop相关的类有5个
            - [x] 1.CFRunLoopRef
            - [x] 2.CFRunLoopModeRef
            - [x] 3.CFRunLoopSourceRef
            - [x] 4.CFRunLoopTimerRef
            - [x] 5.CFRunLoopObserverRef
        那么每个类都是什么呢?
            - [x] 1.第一个类我在前面已经剖析过了,它就是RunLoop对象所属于的类
            - [x] 2.CFRunLoopModeRef 是 RunLoop 当前的一个运行模式,什么是运行模式呢?我会在RunLoop和Mode这一节仔细讲解
            - [x] 3.CFRunLoopSourceRef和CFRunLoopTimerRef是RunLoop处理的消息类型
            - [x] 4.CFRunLoopObserverRef监听RunLoop运行状态的一个类
        各个类之间的关系
            - [x] 1.一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer。
            - [x] 2.每次调用 RunLoop的主函数时,只能指定其中一个 Mode,这个Mode被称作CurrentMode。
            - [x] 3.如果需要切换 Mode,只能退出Loop,再重新指定一个Mode进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。
            - [x] 4.如果一个 mode中一个Source/Timer/Observer 都没有,则RunLoop会直接退出,不进入循环。
        各个类的作用
            - [x] 1.CFRunLoopRef是一个CFRunLoop结构体的指针,所以说它的职责就是CFRunLoop的职责,运行循环,处理事件,保持运行
            - [x] 2.CFRunLoopModeRef运行模式,模式下对应多个处理源,具体有哪些模式我会在RunLoop和Mode这一节仔细讲解
            3.CFRunLoopSourceRef是事件产生的地方。Source有两个版本:Source0 和 Source1。
                - [x] 1.source0触摸事件处理
                - [x] 2.source1基于Port的线程见通信
            - [x] 4.CFRunLoopTimerRefNSTimer的运用
            - [x] 5.CFRunLoopObserverRef用于监听RunLoop的状态,UI刷新,自动释放池
    RunLoop和线程
        - [x] 1.RunLoop是基于线程来管理的,它们一一对应,共同存储在一个全局区的runLoopDict中,线程是key,RunLoop是value。
        - [x] 2.RunLoop的创建:主线程所对应RunLoop在程序一启动创建主线程的时候系统就会自动为我们创建好,而子线程所对应的RunLoop并不是在子线程创建出来的时候就创建好的,而是在我们获取该子线程所对应的RunLoop时才创建出来的,换句话说,如果你不获取一个子线程的RunLoop,那么它的RunLoop就永远不会被创建。
        - [x] 3.RunLoop的获取:我们可以通过一个指定的线程从runLoopDict中获取它所对应的RunLoop。
        - [x] 4.RunLoop的销毁:系统在创建RunLoop的时候,会注册一个回调,确保线程在销毁的同时,也销毁掉其对应的RunLoop。
    CFRunLoopRef对象源码剖析
        - [x] NSRunLoop对象是基于CFRunLoopRef的,并且CFRunLoopRef是基于c语言的,线程安全
    RunLoop对象的获取
        CoreFoundation
            CFRunLoopRef对象
                - [x] CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
                - [x] CFRunLoopGetMain();   // 获得主线程的RunLoop对象
        Fundation框架 (基于CFRunLoopRef的封装)
            NSRunLoop对象
                - [x] [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
                - [x] [NSRunLoop mainRunLoop];   // 获得主线程的RunLoop对象
    RunLoop在何处开启?
        - [x] 在UIApplicationMain函数中,开启了一个和主线程相关的RunLoop,导致UIApplicationMain不会返回,一直在运行中,也就保证了程序的持续运行
    RunLoop的作用
        1.保持程序持续运行
            - [x] 程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行
        2.处理App中的各种事件
            - [x] 1.定时器(Timer)、方法调用(PerformSelector)
            - [x] 2.GCD Async Main Queue
            - [x] 3.事件响应、手势识别、界面刷新
            - [x] 4.网络请求
            - [x] 5.自动释放池 AutoreleasePool
        3.节省cpu资源,提高程序性能
            - [x] 程序运行起来时,当什么操作都没有做的时候,RunLoop就告诉CUP,现在没有事情做,我要去休息,这时CUP就会将其资源释放出来去做其他的事情,当有事情做的时候RunLoop就会立马起来去做事情
    什么是RunLoop?
        - [x] 之所以,iOS App 能持续响应,保证程序运行状态,在于其有一个事件循环——Event Loop
        - [x] 事件循环机制,即线程能随时响应并处理事件的机制。这种机制要求线程不能退出,而且需要高效的完成事件调度与处理。
        - [x] 事件循环在很多编程语言,或者说不同的操作系统层面都支持。比如 JS中的事件循环、Windows下的消息循环,在 iOS/macOS 下,该机制就称为 RunLoop。
        举一个生活中的????
            - [x] 进程是一家工厂,线程是一个流水线,RunLoop就是流水线上的主管;当工厂接到商家的订单分配给这个流水线时,RunLoop就启动这个流水线,让流水线动起来,生产产品;当产品生产完毕时,RunLoop就会暂时停下流水线,节约资源。
            - [x] RunLoop管理流水线,流水线才不会因为无所事事被工厂销毁;而不需要流水线时,就会辞退RunLoop这个主管,即退出线程,把所有资源释放。
```

(编辑:汽车网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章