iOS RunLoop

作者: iOS_成才录 | 来源:发表于2015-11-12 19:27 被阅读2874次

    一、简介

    • 什么是RunLoop

      • 运行循环
      • 基本作用:
        • 保持程序的持续运行,如果没有RunLoop,程序执行完main函数就结束了。
        • 处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
        • 节省CPU资源,提高程序性能:该做事时做事,该休息时休息
        • ......
    • main函数中的RunLoop

      • 在UIApplicationMain函数内部就启动了一个RunLoop,所以UIApplicationMain函数一直没有返回,保持了程序的持续运行
      • 这个默认启动的RunLoop是跟主线程相关联的
    #import <UIKit/UIKit.h>
    #import "AppDelegate.h"
    
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 
        }
    }
    

    二、RunLoop与线程

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

    获得RunLoop对象

    • iOS中有2套API来访问和使用RunLoop

      • 1.Foundation : NSRunLoop
      • 2.CoreFoundation : CFRunLoopRef
      • NSRunLoop和CFRunLoopRef都代表着RunLoop对象
    • Foundation

    [NSRunLoop currentRunLoop];// 获得当前线程的RunLoop对象
    [NSRunLoop mainRunLoop];// 获得主线程的RunLoop对象
    
    • CoreFoundation
    CFRunLoopGetCurrent();// 获得当前线程的RunLoop对象
    CFRunLoopGetMain();// 获得主线程的RunLoop对象
    

    三、RunLoop相关资料

    四、RunLoop相关类

    • CoreFoundation中关于RunLoop的5个类
      • CFRunLoopRef
      • CFRunLoopModeRef
      • CFRunLoopSourceRef
      • CFRunLoopTimerRef
      • CFRunLoopObserverRef
    runLoop相关类.png

    CFRunLoopModeRef

    • CFRunLoopModeRef代表RunLoop的运行模式

    • 一个 RunLoop包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer

    • 每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode

    • 如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入

    • 这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响

    • 系统默认注册了5个Mode:

      • NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行
    • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode 影响
    • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
    • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
    • NSRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

    CFRunLoopSourceRef

    • CFRunLoopTimerRef是基于时间的触发器
    • CFRunLoopTimerRef基本上说的就是NSTimer,它受RunLoop的Mode影响
    • 注意: GCD的定时器不受RunLoop的Mode影响

    CFRunLoopSourceRef

    • CFRunLoopSourceRef是事件源(输入源)

    • 按照官方文档,Source的分类

      • Port-BasedSources
      • Custom InputSources
      • Cocoa PerformSelector Sources
    • 按照函数调用栈,Source的分类

      • Source0:非基于Port的, 用于用户主动触发事件
      • Source1:基于Port的,通过内核和其他线程相互发送消息

    CFRunLoopObserverRef

    • CFRunLoopObserverRef是观察者, 能够监听RunLoop的状态改变

    • 可以监听的时间点有以下几个

    监听时间点.png
    • 添加Observer
    //创建observer
    CFRunLoopObserverRefobserver = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),kCFRunLoopAllActivities,YES,0,^(CFRunLoopObserverRefobserver, CFRunLoopActivityactivity) {
        NSLog(@"----监听到RunLoop状态发生改变---%zd",activity);
    });
    
    //添加观察者:监听RunLoop的状态
    CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer, kCFRunLoopDefaultMode);
    
    //释放Observer
    CFRelease(observer);
    

    相关文章

      网友评论

      • pengxuyuan:我想问下runLoop相关类.png这个图片的意思 看不懂
      • 海绵宝宝不要哭:可耻,直接copy我文章有意思吗?
        iOS_成才录:@海绵宝宝不要哭 有意思真是
        海绵宝宝不要哭:@iOS_成才录 心知肚明:smile:
        iOS_成才录:@海绵宝宝不要哭 请问哪个是你的?这是我以前笔记而已,只是一个记录而已。其他的我不想多说。
      • li大鹏:iOS开发解答群 163619240 !欢迎
      • 瘾与深巷:楼主你好,CFRunLoopSourceRef这个标题写了两遍,第一个应该是CFRunLoopTimerRef吧!
      • KavinZhou:总结的不错

      本文标题:iOS RunLoop

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