0:补充


1. Both Cocoa and Core Foundation provide _run loop objects_ to help you configure and manage your thread’s run loop


2. A run loop receives events from two different types of sources. Input sources_deliver asynchronous events, usually messages from another thread or from a different application. Timer sources_ deliver synchronous events, occurring at a scheduled time or repeating interval. Both types of source use an application-specific handler routine to process the event when it arrives.


3.In addition to handling sources of input, run loops also generate notifications about the run loop’s behavior. Registered _run-loop observers_ can receive these notifications and use them to do additional processing on the thread. You use Core Foundation to install run-loop observers on your threads.

4. A _run loop mode_ is a collection of input sources and timers to be monitored and a collection of run loop observers to be notified. Each time you run your run loop, you specify (either explicitly or implicitly) a particular “mode” in which to run. During that pass of the run loop, only sources associated with that mode are monitored and allowed to deliver their events. (Similarly, only observers associated with that mode are notified of the run loop’s progress.) Sources associated with other modes hold on to any new events until subsequent passes through the loop in the appropriate mode.


5.
Input Sources :  

          Port-Based Sources
          Custom Input Sources
          Cocoa Perform Selector Sources
          
Timer Sources : timer


6. Performing selectors
  [performSelectorOnMainThread:withObject:waitUntilDone:]
[performSelectorOnMainThread:withObject:waitUntilDone:modes:]
[performSelector:onThread:withObject:waitUntilDone:]
[performSelector:onThread:withObject:waitUntilDone:modes:]
[performSelector:withObject:afterDelay:]
[performSelector:withObject:afterDelay:inModes:]
以上所有方法的runloop必须运行,否则这些方法不会执行,所以有必要判断一下当前的线程的runloop是否执行;

0-0:

//如果没有任何的input source 或 timer 添加到 runloop 中,则此方法立即退出;
     // 此方法运行Mode为NSDefaultRunLoopMode,并一直调用 runMode:beforeDate 方法,也就是说此方法让 runloop 一直执行;
     [[NSRunLoop currentRunLoop] run];
     //如果希望运行循环终止,可以使用下面的方法
     BOOL shouldKeepRunning = YES; // global
     NSRunLoop *theRL = [NSRunLoop currentRunLoop];
     while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
     
     //如果没有任何的input source 或 timer 添加到 runloop 中,则此方法立即退出;
     // 此方法运行Mode为NSDefaultRunLoopMode,并一直调用 runMode:beforeDate 方法, 一直到时间过期
     [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
     
    //如果没有任何的input source 或 timer 添加到 runloop 中,则此方法立即退出;
    // it returns after either the first input source is processed or limitDate is reached
    // A timer is not considered an input source and may fire multiple times while waiting for this method to return
     [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]];

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
1.8k 声望1.2k 粉丝

发上等愿,结中等缘,享下等福;


« 上一篇
python
下一篇 »
iOS 3