zoukankan      html  css  js  c++  java
  • RunLoop

    一、什么是RunLoop

    1. 从字面意思理解:运行循环、跑圈。
    2. 基本作用:
      • 保持程序(应用)的持续运行。
      • 处理程序(APP)中的各种事件(比如:触摸事件、定时事件、Selector事件等)
      • 节省CPU资源,提高程序的性能:调度CPU,该做事时做事,该休息时休息。
    3. 每个程序中的RunLoop是在Main函数中创建的,实际上是在以下代码中创建的
      int main(int argc, char * argv[]) {
          @autoreleasepool {
              return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
          }
      }

    二、RunLoop 对象

    1. iOS中有两套API来访问和使用RunLoop:Foundation(OC,面向对象:NSRunLoop类)、Core Foundation(C,面向对象:CFRunLoop类)
    2. NSRunLoop和CFRunLoop都是代表着RunLoop对象,但是NSRunLoop是基于CFRunLoop的一层OC包装,所以要了解RunLoop的内部结构,需要多研究CFRunLoop层面的API(Core Foundation层面)。

    三、RunLoop与线程

    1. 每条线程都有唯一的一个与之对应的RunLoop对象。
    2. 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。 
    3. RunLoop在第一次获取时创建,在线程结束时销毁。

    四、获取RunLoop对象

    1. Foundation框架
          [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
          [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
    2. Core Foundation框架
          CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
          CFRunLoopGetMain(); // 获得主线程的RunLoop对象

    五、RunLoop 相关类

    1. CFRunLoopRef:RunLoop的对象类。
    2. CFRunLoopModelRef:代表RunLoop的运行模式。
      系统默认注册了5个Model:
      kCFRunLoopDefaultMode: APP的默认Model,通常主线程是在这个Model下运行。
      UITrackingRunLoopMode: 界面跟踪Model,用于Scrollview追踪触摸滑动,保证界面滑动时不受其他Model影响。
      UIInitializationRunLoopModel: 刚启动APP时进入的第一个Model,启动完成后就不再使用。
      GSEventReceiveRunLoopModel: 接受系统事件的内部Model,通常用不到。
      kCFRunLoopCommonModes: 这是一个占位用的Model,不是一种真正的Model。话句话说,是一种标记,这种标记存在以下两种模式中:kCFRunLoopDefaultMode、UITrackingRunLoopMode。
      • 一个RunLoop包含若干个Model,每个Model又包含若干个Source、Timer、Observer。
      • 每次RunLoop启动时,只能指定其中一个Model,这个Model被称作CurrentModel。
      • 如果需要切换Model,只能退出Loop,再重新指定一个Model进入。
    3. CFRunLoopSourceRef:是事件源(输入源)。
      按照官方文档,Source的分类:
          ① Port-Based Source (系统内核中的事件)。
          ② Custom Input Source (自定义事件)。
          ③ Cocoa Perform Selector Source。
      
      按照函数调用栈,Source的分类:
          ① Source0:非基于Port的。
          ② Source1:基于Port的,通过内核和其他线程通信,接收、分发系统事件。
    4. CFRunLoopTimerRef:是基于时间的触发器,基本上说的就是NSTimer,它是受Model影响的。
    5. CFRunLoopObserverRef:是观察者,能够监听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
              kCFRunLoopAllActivities = 0x0FFFFFFFU // RunLoop的全部活动
          };
      /******************************举例如下****************************************/
          // 添加observer
           CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAlloca  torGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer,  CFRunLoopActivity activity) {
               NSLog(@"---监听到RunLoop的活动状态------%lu", activity);
          });
          // 添加观察者:监听RunLoop的状态
          CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);     
    6. RunLoop 的运行逻辑理解

    六、RunLoop 应用

    1. NSTimer 的使用。
    2. performSelector 的使用。
    3. ImageView的显示。
    4. 常驻子线程。自动释放池(自动释放在进入RunLoop时创建,在RunLoop休眠前(kCFRunLoopBeforeWaiting)释放)。

    七、总结

    1. RunLoop浅层了说就是运行循环;深层次的说它内部就是一个do-while循环,在这个循环中不断的处理各种任务(比如:source、timer、observer)。
    2. 一个线程对于一个RunLoop,主线程的RunLoop默认是自动开启的,子线程的RunLoop需要手动去启动(调用RunLoop的run方法)。
    3. RunLoop只能选择一种Model启动,如果当前Model中没有Source(source0、source1)、Timer,那么就会直接退出RunLoop(注意:添加Observer进去无效)。
    此文章为个人笔记,方便自己以及有需要的朋友查看,转载请注明出处!
  • 相关阅读:
    Ansible跳板机自动部署
    nginx展示文件目录
    【转】消息钩子注册浅析
    windows临界区
    windbg定位死锁
    Windows工作集内存
    我的spring boot,杨帆、起航!
    CursorFileManager对cursor文件的读写
    eclipse执行maven install命令时跳过test
    bASE--Risk
  • 原文地址:https://www.cnblogs.com/shpyoucan/p/6051367.html
Copyright © 2011-2022 走看看