• 理解RunLoop


    一、什么是RunLoop?

    从字面意思上来看,RunLoop就是运行循环,跑圈的意思。

    我们都知道,一般来说一个线程执行一次任务之后便会退出,在iOS中,如果主线程只执行一次便退出的话也就意味着程序的停止。那么它是怎样做到让主线程保持不死,让程序一直运行的呢?答案就是RunLoop了。

    打个比方:

    如果没有RunLoop,程序在第三行后便结束了。

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

    二、main函数中的RunLoop

    int main(int argc, char * argv[]) {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }

    UIApplicationMain函数内部就启动了一个RunLoop,所以UIApplicationMain一直没有返回,保持了程序的一直运行,这个默认启动的RunLoop是和主线程相关联的

    三、RunLoop与线程

    1.每条线程都有唯一的一个与之对应的RunLoop对象,实现内部是一个全局的字典,key->线程名 value->runloop

    2.主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建

    3.RunLoop在第一次获取时创建,在线程结束时销毁

    四、RunLoop相关类

    Core Foundation中关于RunLoop的5个类

    CFRunLoopRef

    CFRunLoopModeRef

    CFRunLoopSourceRef

    CFRunLoopTimerRef

    CFRunLoopObserverRef
    a.CFRunLoopModeRef:
    1.CFRunLoopModeRef代表RunLoop的运行模式
    2.一个 RunLoop 包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
    3.每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode
    4.如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入,这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响
    5.系统默认注册了5个Mode:
    NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行
    UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
    UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
    GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
    NSRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
    b.CFRunLoopTimerRef
    1.CFRunLoopTimerRef是基于时间的触发器
    2.CFRunLoopTimerRef基本上说的就是NSTimer,它受RunLoop的Mode影响
    3.GCD的定时器不受RunLoop的Mode影响
    c.CFRunLoopSourceRef
    CFRunLoopSourceRef是事件源(输入源)
    按照官方文档,Source的分类
    Port-Based Sources

    Custom Input Sources

    Cocoa Perform Selector Sources

     按照函数调用栈,Source的分类

    Source0:非基于Port的

    Source1:基于Port的,通过内核和其他线程通信,接收、分发系统事件


    d.CFRunLoopObserverRef

    CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变

     

    五、RunLoop应用

    NSTimer:

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

    1.调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode

    2.定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作

    3.标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode

    4.runloop Mode里如果没有timer/source/observer 不会开启成功

    ImageView显示
    PerformSelector
    常驻线程
    自动释放池
  • 相关阅读:
    Element 更新以及全局设置属性
    第二次作业
    软件工程---自我介绍
    git lfs
    SUID
    G1 log 解析
    CMS jvm flags详解
    java不安全证书报证书路径找不到问题
    记一次CMS unloading class 耗时长调查
    springboot jsp 在Linux中报404问题
  • 原文地址:https://www.cnblogs.com/tmacforever/p/5207616.html
Copyright © 2020-2023  润新知