Runloop

1:runloop是什么?

runloop是一个循环,它是程序运行的基石;主要功能有:
能够保持程序的持续运行
处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
提高程序性能:有事件需要处理就运行起来;没有任务的时候处于睡眠状态;节省CPU资源;

UIApplication 中一直开启一个runloop来保证程序正常运行.

2:runloop与线程之间的关系

每条线程都有唯一的一个与之对应的RunLoop对象(主线程runloop默认开启,子线程runloop需要手动开启)RunLoop在第一次获取时创建,在线程结束时销毁

3.runloop相关类介绍:

CFRunLoopModeRef:
  一个RunLoop包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
  每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode(当且仅当指定一个mode)
  如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入
  这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响
  
  ModeType:
  kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
  UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响
  UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
  GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
  kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode(是几种mode的集合)
  
CFRunLoopSourceRef
  CFRunLoopSourceRef是事件源(输入源)可以分为两类:
  Port-Based Sources (基于端口,跟其他线程交互,通过内核发布的消息)
  Custom Input Sources (自定义类型)
  Cocoa Perform Selector Sources (performSelector…方法)
  包含两种事件:Source0(大多是自定义方法), Source1(基于系统)
  Source0: event事件,只含有回调,需要先调用CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop。
Source1: 包含了一个 mach_port 和一个回调,被用于通过内核和其他线程相互发送消息,能主动唤醒 RunLoop 的线程

CFRunLoopObserverRef:
  observer:顾名思义就是一个观察者;来观察runloop不同的状态
  /* Run Loop Observer Activities */
  typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
      kCFRunLoopEntry = (1UL << 0), //进入runloop
      kCFRunLoopBeforeTimers = (1UL << 1), //开始处理timer事件之前
      kCFRunLoopBeforeSources = (1UL << 2), //开始处理source事件钱
      kCFRunLoopBeforeWaiting = (1UL << 5), //开始睡眠之前
      kCFRunLoopAfterWaiting = (1UL << 6), //唤醒之后
      kCFRunLoopExit = (1UL << 7), //退出
      kCFRunLoopAllActivities = 0x0FFFFFFFU
};
  

3.runloop处理事件的步骤:
e004412fc56ab75a4e5d53275a4bd41c.jpg
4.runloop实际应用

  1.滑动scrollView轮播图轮播失效,是由于定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作.而滑动的时候是trakingMode;解决方法:timer 添加到runloop的commonMode
  2.当滑动scrollView时候改变imageView图片
    (1)可以监听scrollView滑动事情来做
    (2) [imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"trakingModeImageName"] afterDelay:3.0 inModes:@[UITrackingRunLoopMode]];
  3.常驻线程
   (1)粗暴的方法 while(YES){} 
   (2)添加source
      [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
   启动RunLoop:[[NSRunLoop currentRunLoop] run]; 退出:[NSThread exit];
 

参考内容:
http://ios.jobbole.com/85635/…
https://developer.apple.com/l…
http://opensource.apple.com/s…

    原文作者:Stephanie
    原文地址: https://segmentfault.com/a/1190000011090651
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞