浅析 RunLoop

来源:互联网 发布:数控编程图纸大全 编辑:程序博客网 时间:2024/04/30 00:36

一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生。给我们的感觉就像应用一直处于随时待命的状态,在没人操作的时候它一直在休息,在让它干活的时候,它就能立刻响应。其实,这就是RunLoop作用,从字面意思看:就是运行循环/跑圈(实际上底层是一个庞大的C语言do while循环)


RunLoop作用:

保持程序的持续运行,

处理app中各种事件(触摸事件,定时事件,selector事件)

节省cpu资源,提高程序性能,该做事做事,该休息休息

官方图解:

这里写图片描述


RunLoop模式(CFRunLoopModeRef)

kCFRunLoopDefaultMode: App默认Mode,通常主线程是在这个Model下运行UITrackingRunLoopMode: 界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不收其他Mode影响NSRunLoopCommonModes: 占位用的Mode,默认包括上面两个,不是真正的ModeUIInitializationRunLoopMode: 私有,App启动时

一个RunLoop中可以有多个模式,但是同一时间只可以选择一种模式运行,切换另一种模式时,需要推出当前模式,但在每一种模式下,处理的内容有三大块:Source、Observer、Timer

这里写图片描述


RunLooop与NSTimer(CFRunLoopTimerRef)

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];// 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 定时器只运行在UITrackingRunLoopMode下(拖拽ScrollView会来到这个模式),一旦RunLoop进入其他模式,这个定时器就不会工作[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];// 标记为NSRunLoopCommonModes的模式:会运行在UITrackingRunLoopMode或NSDefaultRunLoopMode模式下(注意只能运行在一种模式下,“或”)[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];----------// 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopModeNSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];// 修改模式[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
附:CADisplayLink的工作也是添加到RunLoop中的,从CADisplayLink提供的方法可以看出 + (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel; + (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode; + (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;

RunLooop与Source(CFRunLoopSourceRef)

CFRunLoopSourceRef是事件源(输入源),比如点击事件,触摸事件…

按照官方文档分类,Source可分为:

  • Port-Base Source:基于端口,和其他线程进行交互
  • Custom Input Source:自定义输入源
  • Cocoa Perform Selector Source:performSelector相关函数

按照函数调用栈,Source可分为:

  • Source0:非基于Port的,接收点击事件,触摸事件等等,比如某个按钮点击的调用栈
    这里写图片描述
  • Source1:基于Port的,通过内核和其他线程通信,接收,分发系统事件(大部分事件都是由屏幕表面包装成Event,然后分发下去,由Source0去处理)

RunLooop与Observer(CFRunLoopObserverRef)

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

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {    kCFRunLoopEntry = (1UL << 0),            //即将进入Loop    kCFRunLoopBeforeTimers = (1UL << 1),     //即将处理Timer    kCFRunLoopBeforeSources = (1UL << 2),    //即将处理Source    kCFRunLoopBeforeWaiting = (1UL << 5),    //即将进入休眠    kCFRunLoopAfterWaiting = (1UL << 6),     //刚从休眠中唤醒    kCFRunLoopExit = (1UL << 7),             //即将退出Loop    kCFRunLoopAllActivities = 0x0FFFFFFFU    //所有状态};
// 创建observerCFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {    NSLog(@"----监听到RunLoop状态---%zd", activity);});// 添加观察者:监听RunLoop的状态CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);// 释放ObserverCFRelease(observer);附:CF的内存管理(Core Foundation)ARC环境下是创建的”OC对象“不需要手动释放,但是Core Foundation里(C层面)的仍然需要手动管理,不受ARC管理1.凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release* 比如CFRunLoopObserverCreate2.release函数:CFRelease(对象);

RunLoop处理逻辑

这里写图片描述

0 0
原创粉丝点击