Runloop简介

来源:互联网 发布:考古电影知乎 编辑:程序博客网 时间:2024/05/14 03:08
(一)概念
  • 运行循环
  • 保持程序持续运行
  • 处理app的各种事件(比如触摸事件、定时器事件、Selector事件)

1.Runloop与线程
  • 每条线程都有唯一的与之对应的RunLoop对象
  • 主线程的runloop是自动创建好的,子线程的runloop需要手动创建
  • RunLoop在第一次获取时创建,在线程结束时销毁。而如果该RunLoop不包含任何Timer、Source、Observer,它就会自我销亡


(二)Runloop相关类
  • 在 CoreFoundation 里面关于 RunLoop 有5个类:
  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef:事件源 
  • CFRunLoopTimerRef:基于时间的触发器
  • CFRunLoopObserverRef:观察者

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


(三)CFRunLoopModeRef
1.常用Mode
  • NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行
  • UITrackingRunLoopMode:界面跟踪Mode。用于追踪ScrollView的触摸滑动事件,保证界面滑动时不收其他Mode影响。
  • NSRunLoopCommonModes:这是一个占位用的Mode(综合以上两种模式),不是一中真正的Mode。

2.使用
  • 一个 RunLoop 包含若干个 Mode(模式),每个 Mode 又包含若干个Source/Timer/Observer。每次调用 RunLoop 的主函数时,只能指定一个 Mode,这个Mode被称作 CurrentMode(当前模式)。如果需要切换 Mode,只能退出当前 Loop,再重新指定一个 Mode 进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。

(四)CFRunLoopSourceRef
1.按官方文档分类
  • Port-Base Source:继续端口的,与其他线程进行交互
  • Custom Input Source
  • Cocoa Perform Selector Source

2.根据函数调用栈分类:
  • Source0:非基于Port的。
  • Source1:基于Port的,通过内核和其他线程通信,接受、分发系统事件。
  • Source1接收到事件后,会交给Source0去处理


(五)CFRunLoopTimerRef
  • CFRunLoopTimerRef基本上就是NSTimer,它受RunLoop的Mode影响。
  • GCD的定时器不受RunLoop的Mode影响。
  • ① NSTimer默认加入RunLoop,且是NSDefaultRunLoopMode

//调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,默认是NSDefaultRunLoopMode
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:selfselector:@selector(run) userInfo:nil repeats:YES];
   
   
 // 修改模式
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];


  • ②三种模式分析

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:selfselector:@selector(run) userInfo:nil repeats:YES];
   
 // 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    [[
NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
   
   
 // 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    [[
NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
   
   
 // 定时器会跑在标记为common modes的模式下
   
 // 标记为common modes的模式:UITrackingRunLoopModeNSDefaultRunLoopMode
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];


(六)Oberserver(观察者)
  • CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
  • 可以监听以下几个时间点:

CFRunLoopActivity的取值
    kCFRunLoopEntry = (1UL <<0),
    kCFRunLoopBeforeTimers = (1UL << 1),
    kCFRunLoopBeforeSources = (
1UL << 2),
    kCFRunLoopBeforeWaiting = (
1UL << 5),
    kCFRunLoopAfterWaiting = (
1UL << 6),
    kCFRunLoopExit = (
1UL << 7),
    kCFRunLoopAllActivities = 0x0FFFFFFFU


1.CFRunLoopObserverRef的使用

- (void)observer
{
   
 // 1. 创建observer
   
 CFRunLoopObserverRef observer =CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities,YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
       
 NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
    });

   
 // 2. 添加观察者:监听RunLoop的状态
   
 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
   
   
 // 3. 释放Observer
   
 CFRelease(observer);
}

/*
    CF
的内存管理(Core Foundation
    1.
凡是带有CreateCopyRetain等字眼的函数,创建出来的对象,都需要在最后做一次release
    *
 比如CFRunLoopObserverCreate
    2.release
函数:CFRelease(对象);
 */

0 0