美文网首页
Runloop机制和用处

Runloop机制和用处

作者: 谁在呼叫贱队 | 来源:发表于2021-05-09 14:03 被阅读0次

    Objective-C Runloop机制

    对于RunLoop而言最核心的事情就是保证线程在没有消息的时候休眠,在有消息时唤醒,以提高程序性能。RunLoop这个机制是依靠系统内核来完成的(苹果操作系统核心组件Darwin中的Mach)。
    RunLoop 实际上是一个对象,这个对象在循环中用来处理程序运行过程中出现的各种事件(比如说触摸事件、UI刷新事件、定时器事件、Selector事件),从而保持程序的持续运行。
    RunLoop 在没有事件处理的时候,会使线程进入睡眠模式,从而节省 CPU 资源,提高程序性能。
    在线程创建后,在创建对应的RunLoop
    RunLoop由系统维护在一张表中,其中线程为Key对应的Value是创建的RunLoop
    

    NSTimer,具体化应用

    本质上来讲,NSTimer就是封装的Runloop的最简单体现应用
    NSTimer的创建通常有两种方式,尽管都是类方法,一种是timerWithXXX,另一种scheduedTimerWithXXX
    二者最大的区别就是后者除了创建一个定时器外会自动以NSDefaultRunLoopModeMode添加到当前线程RunLoop中,不添加到RunLoop中的NSTimer是无法正常工作的。
    
    //滚动UIScrollView(UITableView、UICollectionview是类似的)的情况下Timer都会暂停
    -(NSTimer *)timer1{
        if(_timer1 == nil){
            //无法运行,用scheduledTimerWithTimeInterval创建的timer对象必须要放到NSDefaultRunLoopMode中
            _timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timeInterval:) userInfo:nil repeats:YES];
        }
        return _timer1;
    }
    
    -(NSTimer *)timer2{
        if(_timer2 == nil){
            _timer2 = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timeInterval:) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop]addTimer:_timer2 forMode:NSDefaultRunLoopMode];
        }
        return _timer2;
    }
    

    生命周期

        /* Run Loop Observer Activities */
        typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
            kCFRunLoopEntry = (1UL << 0), // 进入RunLoop 
            kCFRunLoopBeforeTimers = (1UL << 1), // 即将开始Timer处理
            kCFRunLoopBeforeSources = (1UL << 2), // 即将开始Source处理
            kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
            kCFRunLoopAfterWaiting = (1UL << 6), //从休眠状态唤醒
            kCFRunLoopExit = (1UL << 7), //退出RunLoop
            kCFRunLoopAllActivities = 0x0FFFFFFFU
        };
    

    额外用处

    //延迟方法的执行,在延迟4s并且在滑动结束后调用
    [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"tupian"] afterDelay:4.0 inModes:@[NSDefaultRunLoopMode]];
    

    源码备注

    int32_t __CFRunLoopRun()
    {
        // 通知即将进入runloop ------(声明周期一)------
        __CFRunLoopDoObservers(KCFRunLoopEntry);
        
        do
        {
            // 通知将要处理timer和source  ------(声明周期二和三)------
            __CFRunLoopDoObservers(kCFRunLoopBeforeTimers);
            __CFRunLoopDoObservers(kCFRunLoopBeforeSources);
            // 处理非延迟的主线程调用
            __CFRunLoopDoBlocks();
            // 处理Source0事件
            __CFRunLoopDoSource0();
            
            if (sourceHandledThisLoop) {
                __CFRunLoopDoBlocks();
             }
            /// 如果有 Source1 (基于port) 处于 ready 状态,直接处理这个 Source1 然后跳转去处理消息。
            if (__Source0DidDispatchPortLastTime) {
                Boolean hasMsg = __CFRunLoopServiceMachPort();
                if (hasMsg) goto handle_msg;
            }
            /// 通知 Observers: RunLoop 的线程即将进入休眠(sleep)。 ------(声明周期四)------
            if (!sourceHandledThisLoop) {
                __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeWaiting);
            }
            // GCD dispatch main queue
            CheckIfExistMessagesInMainDispatchQueue();
            // 即将进入休眠。 ------(声明周期五)------
            __CFRunLoopDoObservers(kCFRunLoopBeforeWaiting);
            // 等待内核mach_msg事件
            mach_port_t wakeUpPort = SleepAndWaitForWakingUpPorts();
            // 等待。。。
            // 从等待中醒来
            __CFRunLoopDoObservers(kCFRunLoopAfterWaiting);
            // 处理因timer的唤醒
            if (wakeUpPort == timerPort)
                __CFRunLoopDoTimers();
            // 处理异步方法唤醒,如dispatch_async
            else if (wakeUpPort == mainDispatchQueuePort)
                __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()
            // 处理Source1
            else
                __CFRunLoopDoSource1();
            // 再次确保是否有同步的方法需要调用
            __CFRunLoopDoBlocks();
        } while (!stop && !timeout);
        // 通知即将退出runloop
        __CFRunLoopDoObservers(CFRunLoopExit);
    }
    

    相关文章

      网友评论

          本文标题:Runloop机制和用处

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