iOS开发网络多线程之Runloop无限循环

一. Runloop的基本知识

1. 概念api

    runloop是运动循环,不断跑圈,无限循环框架

   做用:
oop

    保持程序的持续运行 (iOS程序一直活着的缘由)
性能

    处理App中的各类事件(eg:触摸事件/定时器事件/selector事件【选择器·performSelector···】)spa

    节省CPU资源,提升程序的性能(有事作事,没事休息)
线程

程序已启动,就开启了一个runloop无限循环,所以程序才能持续的运行code

  
  
  
  
#import <UIKit/UIKit.h>#import "AppDelegate.h"int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}}


2. Runloop对象orm

1> 在iOS开发中有两套api来访问Runloopserver

  • Foundation框架【NSRunloop】(OC)对象

  • Core Foundation框架【CFRunloopRef】(C)

2> NSRunLoop和CFRunLoopRef都表明着RunLoop对象,它们是等价的,能够互相转换

3> NSRunLoop是基于CFRunLoopRef的一层OC包装,因此要了解RunLoop内部结构,须要多研究CFRunLoopRef层面的API(Core Foundation层面)

  

3. Runloop与线程的关系

1> Runloop和线程的关系:一个Runloop对应着一条惟一的线程

    问题:如何让子线程不死

    回答:给这条子线程开启一个Runloop

2> Runloop的建立:主线程Runloop已经建立好了,子线程的runloop须要手动建立

3> Runloop的生命周期:在第一次获取时建立,在线程结束时销毁


二. Runloop对象的建立

1. Foundation框架【NSRunloop】建立Runloop对象

  
  
  
  
// 获取当前线程下的Runloop, 懒加载的形式建立NSRunLoop * runloop1 = [NSRunLoop currentRunLoop];// 获取主线程下的RunloopNSRunLoop * runloop1 = [NSRunLoop mainRunLoop];

2. Core Foundation框架【CFRunloopRef】建立Runloop对象

  
  
  
  
// 获取当前线程下的Runloop, 懒加载的形式建立CFRunLoopRef runloop2 = CFRunLoopGetCurrent();// 获取主线程下的RunloopCFRunLoopRef runloop2 = CFRunLoopGetMain();


3. Runloop运行原理图

4. Runloop相关的类

  • CFRunloopRef

  • CFRunloopModeRefRunloop的运行模式】

  • CFRunloopSourceRefRunloop要处理的事件源】

  • CFRunloopTimerRefTimer事件】

  • CFRunloopObserverRefRunloop的观察者(监听者)】

    Runloop要想跑起来,它的内部必需要有一个mode,mode中必须有source/observer/time,至少要有其中的一个

 

5. CFRunloopModeRefRunloop的运行模式】

    Runloop每次启动的时候只能指定一个运行模型,切换模式时必须退出当前的Runloop,再从新进入一个mode,是为了分割不一样组的定时器互不影响

  • kCFRunLoopDefaultMode:App的默认Mode,一般主线程是在这个Mode下运行

  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其余 Mode 影响

  • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就再也不使用

  • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,一般用不到

  • kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

6. CFRunloopTimerRefTimer事件】

1> NSTimer

  
  
  
  
- (void)timer0{NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(show) userInfo:nil repeats:YES];/* NSDefaultRunLoopMode -> kCFRunLoopDefaultMode 默认模式主线程中执行 NSRunLoopCommonModes -> kCFRunLoopDefaultMode/UITrackingRunLoopMode UITrackingRunLoopMode -> 界面追踪,其余不工做 */[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];}

2. GCD定时器

GCD定时器必须必须保存起来才能使用

  
  
  
  
- (void)gcdTimer{NSLog(@"+++++++++");// 1.建立定时器dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));// 2.设置定时器/* 第一个参数:定时器 第二个参数:从哪一个时间开始 第三个参数:间隔时间 第四个参数:精确度, 0表明无偏差 */ dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);// 3.定时器触发事件 dispatch_source_set_event_handler(timer, ^{NSLog(@"----------");});// 4.开启定时器 dispatch_resume(timer);// GCD定时器建立是个局部变量须要保存才能执行 self.timer = timer;}

7. CFRunloopSourceRefRunloop要处理的事件源】

1)之前的分法

Port-Based Sources

Custom Input Sources

Cocoa Perform Selector Sources


2)如今的分法

Source0:非基于Port的 (用户触发的时间)

Source1:基于Port的 (经过内核和其它线程相互发送消息)


8. CFRunloopObserverRefRunloop的观察者(监听者)】

  
  
  
  
- (void)observer{// 建立一个观察者/* 第一个参数:获取内存的方式 第二个参数:监听哪些状态 第三个参数:是否持续监听 第四个参数:0 第五个参数:block代码块 kCFRunLoopEntry = (1UL << 0), 准备进入 kCFRunLoopBeforeTimers = (1UL << 1), 即将处理timer事件 kCFRunLoopBeforeSources = (1UL << 2), 即将处理source事件 kCFRunLoopBeforeWaiting = (1UL << 5), 即将进入休眠 kCFRunLoopAfterWaiting = (1UL << 6), 唤醒 kCFRunLoopExit = (1UL << 7), 退出 kCFRunLoopAllActivities = 0x0FFFFFFFU 全部 */CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {switch (activity) {case kCFRunLoopEntry:NSLog(@"准备进入");break;case kCFRunLoopBeforeTimers:NSLog(@"即将处理timer事件");break;case kCFRunLoopBeforeSources:NSLog(@"即将处理source事件");break;case kCFRunLoopBeforeWaiting:NSLog(@"即将进入休眠");break;case kCFRunLoopAfterWaiting:NSLog(@"唤醒");break;case kCFRunLoopExit:NSLog(@"退出");break;}});// 给runloop添加一个观察者CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(show) userInfo:nil repeats:YES];// 释放观察者CFRelease(observer);}


9. Runloop运行逻辑


相关文章
相关标签/搜索