iOS Runloop简析

作者: 飞不越疯人院 | 来源:发表于2019-04-26 18:20 被阅读5次

    1. 什么是Runloop?

      1. Runloop是通过内部维持事件循环来对事件/消息进行管理的一个对象;
    • 2.runloop跟线程是一一对应的;
      1. NSRunLoopCFRunLoopRef是所说的Runloop的具体类;CFRunLoopRefCoreFoundation框架内的C实现的, 线程安全; NSRunLoop是基于CFRunloopRef的封装,不是线程安全的;
      1. 主线程的Runloop是主动创建启动的, 子线程的Runloop需要手动获取;

    事件循环:没有消息处理时会处于休眠状态避免资源占用(用户态->内核态);有事件处理时会立刻唤醒(内核态->用户态);


    2. 为什么main函数能保持不退出?

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

    main函数本质上是调用UIApplicationMain函数; 在UIApplicationMain函数内部创建了main runloop, 根据runloop的特点, 它可以不断的接收处理消息, 处理完事件后继续等待; 它就这样一直这样在内核态用户态之间切换循环下去 ; 所以main函数不会被退出;


    3. Runloop的各种Mode?

      1. NSDefaultRunLoopMode 默认模式, 主线程在这个模式下运行;
      1. UITrackingRunLoopMode 界面跟踪模式, 例如滚动UITableview时将切换到这种模式, 保证滑动时不受其他Mode影响;
      1. UIInitializationRunLoopMode 启动APP时进入的第一个Mode,启动完成后不再使用;
      1. GSEventReceiveRunLoopMode 接受系统内部事件的Mode;
      1. NSRunLoopCommonModes

    CommonMode不是实际存在的一种Mode;
    它是同步Source/Timer/Observer到多个Mode中的一种方案;


    Runloop对象可以包含多个Mode, 而每个Mode包含多个timer, observer, 'source';

    知识点:如何解决UITableView上轮播图在滚动时失效的问题?
    主线程的Mode有两种模式, 默认是NSDefaultRunLoopMode模式, 当滚动tableView时回切换到UITrackingRunLoopMode模式, 这时轮播图的timer就会失效, 将timer添加到NSRunLoopCommonModes可以解决这个问题;

    4. 怎样实现一个常驻线程?

      1. 为当前线程开启Runloop;
      1. 向该Runloop中添加一个Port/Source等维持Runloop的事件循环;
      1. 启动该Runloop;
     ///创建一个source     这里为什么这样写?
        CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
        ///当一个runloop中没有事件源处理时, 运行完就会退出;
        CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
        ///1. 2. 创建runloop 同时向runloop中的defaultMode下面添加source
        CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
        ///3. 启动runloop
        while (shouldRun) {
            @autoreleasepool {
                ///令当前的runloop运行在defaultMode下
                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true);
            }
        }
        ///某个时机, 将静态变量shouldRun = NO时, 退出runloop, 进而退出线程;
        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
        CFRelease(source);
    

    文中示例代码


    参考文章
    用户态和内核态
    iOS UIApplicationMain函数做了什么
    iOS 深入理解RunLoop
    iOS 简单监测iOS卡顿的demo
    iOS 多线程技术之二RunLoop

    相关文章

      网友评论

        本文标题:iOS Runloop简析

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