美文网首页
关于RunLoop中Mode的相关概念和实现(一)

关于RunLoop中Mode的相关概念和实现(一)

作者: LifeYet | 来源:发表于2015-12-29 20:52 被阅读140次

    一、相关概念:

    • 首先,RunLoop是iOS/OS X开发中非常基础的一个概念,我们先来看一下有关它的概念和实现方法:
      正常来说,一个线程一般只能执行一个任务,执行完成后线程就会退出。现在我们需要一个机制,让线程能随时处理事件但不退出,一般逻辑代码是这样的:
    function loop() {
        initialize();
        do {
            var message = get_next_message();
            process_message(message);
        } while (message != quit);
    }
    
    1. kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。
    1. UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。
    1. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。
    1. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。

    5.NSRunLoopCommonModes: 包含 1 和 2 一般来说包含 UITrackingRunLoopMode 和 NSDefaultRunLoopMode

    二、RunLoop的实现

    // 底层的实现函数
    
    SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled){
    
    // 配置RunLoop的Mode
    
    SetupCFRunLoopMode()
    
    // 通知 Observers 将要进入 Loop
    
    __CFRunLoopDoObservers(kCFRunLoopEntry);
    
    // 通过GCD设置RunLoop的超时时间
    
    SetupThisRunLoopRunTimeoutTimer();
    
    // RunLoop开始处理事件  do while 循环
    
    do {
    
    // 通知 Observers 将执行timer
    
    __CFRunLoopDoObservers(kCFRunLoopBeforeTimers);
    
    // 通知 Observers 将执行Source0
    
    __CFRunLoopDoObservers(kCFRunLoopBeforeSources);
    
    // 执行blocks
    
    __CFRunLoopDoBlocks();
    
    // 执行Source0
    
    __CFRunLoopDoSource0();
    
    // 问 GCD 主线程有没有需要执行的东西
    
    CheckIfExistMessagesInMainDispatchQueue();
    
    // 通知 Observers 将进入睡眠
    
    __CFRunLoopDoObservers(kCFRunLoopBeforeWaiting);
    
    /* 指定 唤醒端口
    
    监听 mach_msg 会停在这里
    
    进入 mach_msg_trap 状态
    
    睡眠中...
    
    */
    
    var wakeUpPort = SleepAndWaitForWakingUpPorts();
    
    // 接收到 消息  通知Observers RunLoop被唤醒了
    
    __CFRunLoopDoObservers(kCFRunLoopAfterWaiting);
    
    // 处理事件
    
    if (wakeUpPort == timerPort) {
    
    // 唤醒端口是 timerPort 执行timer回调 /* DOES CALLOUT */
    
    __CFRunLoopDoTimers();
    
    } else if (wakeUpPort == mainDispatchQueuePort) {
    
    // 唤醒端口 执行mainQueue里面的调用
    
    __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()
    
    } else {
    
    // 唤醒端口 执行Source1回调
    
    __CFRunLoopDoSource1();
    
    }
    
    // 执行 blocks
    
    __CFRunLoopDoBlocks();
    
    // 当事件处理完了、被强制停止了、超时了、Mode是空的时候就会退出 循环
    
    } while (!stop && isStopped !timeout && !ModeIsEmpty );
    
    // 通知 Observers 将退出Loop
    
    __CFRunLoopDoObservers(kCFRunLoopExit);
    
    }
    

    说明:本文章仅供学习交流使用

    相关文章

      网友评论

          本文标题:关于RunLoop中Mode的相关概念和实现(一)

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