zoukankan      html  css  js  c++  java
  • iOS RunLoop

    • 什么是RunLoop
      • 运行循环
      • 一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(调用run方法)
      • RunLoop只能选择一个Mode启动,如果当前Mode中没有任何Source(Sources0、Sources1)、Timer,那么就直接退出RunLoop
    • RunLoop作用

      • 保持程序的持续运行
      • 处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
      • 节省CPU资源,提高程序性能:该做事时做事,该休息时休息 ......
    • 模拟RunLoop内部实现

      • 其实它内部就是do-while循环,在这个循环内部不断地处理各种任务(比如Source、Timer、Observer)
      • void message(int num)
        {
            printf("执行第%i个任务", num);
        }
        int main(int argc, const char * argv[]) {
            do {
                printf("有事吗? 没事我睡了");
                int number;
                scanf("%i", &number);
                message(number);
            } while (1);
            return 0;
        }
    • 获得RunLoop对象

      • RunLoop对象
        • NSRunLoop
        • CFRunLoopRef
      • Foundation
        [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
        [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
        
      • Core Foundation
        CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
        CFRunLoopGetMain(); // 获得主线程的RunLoop对象
        
    • RunLoop结构

    • CFRunLoopRef对应RunLoop对象
      • CFRunLoopModeRef代表RunLoop的运行模式, 系统默认注册了5个Mode
        • NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行
        • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
        • NSRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
      • CFRunLoopTimerRef是基于时间的触发器
        • CFRunLoopTimerRef基本上说的就是NSTimer,它受RunLoop的Mode影响
      • CFRunLoopSourceRef是事件源(输入源)
      • CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
      • // 1.创建Observer
            // 第一个参数:用于分配该observer对象的内存
            // 第二个参数:用以设置该observer所要关注的的事件
            // 第三个参数:用于标识该observer是在第一次进入run loop时执行, 还是每次进入run loop处理时均执行
            // 第四个参数:用于设置该observer的优先级
            // 第五个参数: observer监听到事件时的回调block
            CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
                switch(activity)
                {
                    case kCFRunLoopEntry:
                        NSLog(@"即将进入loop");
                        break;
                    case kCFRunLoopBeforeTimers:
                        NSLog(@"即将处理timers");
                        break;
                    case kCFRunLoopBeforeSources:
                        NSLog(@"即将处理sources");
                        break;
                    case kCFRunLoopBeforeWaiting:
                        NSLog(@"即将进入休眠");
                        break;
                    case kCFRunLoopAfterWaiting:
                        NSLog(@"刚从休眠中唤醒");
                        break;
                    case kCFRunLoopExit:
                        NSLog(@"即将退出loop");
                        break;
                    default:
                        break;
                }
            });
        
            // 2.添加监听
            /*
             第一个参数: 给哪个RunLoop添加监听
             第二个参数: 需要添加的Observer对象
             第三个参数: 在哪种模式下监听
             */
            CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
        
            // 3,释放observer
            CFRelease(observer);
    • RunLoopRunLoop处理逻辑
    • RunLoopRunLoop应用
      • NSTimer
        • 只能在指定的model下运行
        • NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
          [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
      • ImageView显示
        • 只能在指定的model下设置图片
      • PerformSelector
        • 只能在指定的model下调用
        • [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:@"lnj"] waitUntilDone:YES modes:@[NSDefaultRunLoopMode]];
      • 常驻线程
        • 必须调用run才会执行死循环
        • NSRunLoop的model中必须有source/timer,死循环才不会退出
        • NSRunLoop *runloop = [NSRunLoop currentRunLoop];
          [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
          [runloop run]
      • 自动释放池
        • activities = 0x1 = 1
          1: 即将进入RunLoop : 创建一个自动释放池
          activities = 0xa0 = 160 = 128 + 32
          32:即将休眠 : 释放上一次的自动释放池, 创建一个新的自动释放池
          128:即将退出RunLoop : 释放自动释放池

     

  • 相关阅读:
    tp5.1接入支付宝网站支付
    go类型转换
    mysql常见sql练习题
    php 获取当前时间的 前一小时、一天、一个月、一年
    php如何检测是否有环
    Go的切片:长度和容量
    go实现小项目
    知乎网页版不登录如何浏览内容
    图挂了
    centos搭建php环境
  • 原文地址:https://www.cnblogs.com/liujiaoxian/p/4881681.html
Copyright © 2011-2022 走看看