一.NSRunLoop

在Cocoa中,每个线程(NSThread)对象中内部都有一个run loop(NSRunLoop)对象用来循环处理输入事件,处理的事件包括两类,一是来自Input sources的异步事件,一是来自Timer sources的同步事件;
run Loop在处理输入事件时会产生通知,可以通过Core Foundation向线程中添加run-loop observers来监听特定事件,以在监听的事件发生时做附加的处理工作。

每个run loop可运行在不同的模式下,一个run loop mode是一个集合,其中包含其监听的若干输入事件源,定时器,以及在事件发生时需要通知的run loop observers。运行在一种mode下的run loop只会处理其run loop mode中包含的输入源事件,定时器事件,以及通知run loop mode中包含的observers。
Cocoa中的预定义模式有:

  • Default模式
    定义:NSDefaultRunLoopMode (Cocoa) kCFRunLoopDefaultMode (Core Foundation)
    描述:默认模式中几乎包含了所有输入源(NSConnection除外),一般情况下应使用此模式。
  • Connection模式
    定义:NSConnectionReplyMode(Cocoa)
    描述:处理NSConnection对象相关事件,系统内部使用,用户基本不会使用。
  • Modal模式
    定义:NSModalPanelRunLoopMode(Cocoa)
    描述:处理modal panels事件。
  • Event tracking模式
    定义:UITrackingRunLoopMode(iOS) NSEventTrackingRunLoopMode(cocoa)
    描述:在拖动loop或其他user interface tracking loops时处于此种模式下,在此模式下会限制输入事件的处理。例如,当手指按住UITableView拖动时就会处于此模式。
  • Common模式
    定义:NSRunLoopCommonModes (Cocoa) kCFRunLoopCommonModes (Core Foundation)
    描述:这是一个伪模式,其为一组run loop mode的集合,将输入源加入此模式意味着在Common Modes中包含的所有模式下都可以处理。在Cocoa应用程序中,默认情况下Common Modes包含default modes,modal modes,event Tracking modes.可使用CFRunLoopAddCommonMode方法想Common Modes中添加自定义modes。

获取当前线程的run loop mode

NSString* runLoopMode = [[NSRunLoop currentRunLoop] currentMode];

二.NSTimer、NSURLConnection与UITrackingRunLoopMode

NSTimer与NSURLConnection默认运行在default mode下,这样当用户在拖动UITableView处于UITrackingRunLoopMode模式时,NSTimer不能fire,NSURLConnection的数据也无法处理。
NSTimer的例子:
在一个UITableViewController中启动一个0.2s的循环定时器,在定时器到期时更新一个计数器,并显示在label上。

-(void)viewDidLoad
{label =[[[UILabel alloc]initWithFrame:CGRectMake(10, 100, 100, 50)]autorelease];[self.view addSubview:label];count = 0;NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1target: selfselector: @selector(incrementCounter:)userInfo: nilrepeats: YES];
}- (void)incrementCounter:(NSTimer *)theTimer
{count++;label.text = [NSString stringWithFormat:@"%d",count];
}

在正常情况下,可看到每隔0.2s,label上显示的数字+1,但当你拖动或按住tableView时,label上的数字不再更新,当你手指离开时,label上的数字继续更新。当你拖动UItableView时,当前线程run loop处于UIEventTrackingRunLoopMode模式,在这种模式下,不处理定时器事件,即定时器无法fire,label上的数字也就无法更新。
解决方法,一种方法是在另外的线程中处理定时器事件,可把Timer加入到NSOperation中在另一个线程中调度;还有一种方法时修改Timer运行的run loop模式,将其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

NSURLConnection也是如此,见SDWebImage中的描述,以及SDWebImageDownloader.m代码中的实现。修改NSURLConnection的运行模式可使用scheduleInRunLoop:forMode:方法。

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]autorelease];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];

参考:
Threading Programming Guide – Run Loops
NSRunLoop Class Reference
NSURLConnection Class Reference
NSTimer Class Reference
CFRunLoop wiki
SDWebImage
TestButtonDown
NSTimerDoesntRunWhenMenuClicked

http://www.winddisk.com/2012/06/29/nstimer_run_loop_modes/

http://blog.csdn.net/jasonblog/article/details/7854693

转载于:https://www.cnblogs.com/Piosa/archive/2012/10/30/2746652.html

NSTimer 与 Run loop Modes相关推荐

  1. NSTimer与Run loop Modes

    本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接. 本文永久链接: http://www.winddisk.com/2012/06/29/nstimer_run_loop_modes/ ...

  2. ios跨线程通知_iOS多线程编程指南(三)Run Loop

    Run loops是线程相关的的基础框架的一部分.一个run loop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件.使用run loop的目的是让你的线程在有工作的时候忙于工作,而没工作 ...

  3. iOS Run Loop

    http://www.cnblogs.com/scorpiozj/ Run loops是线程的基础架构部分.一个run loop就是一个事件处理循环,用来不停的调配工作以及处理输入事件.使用run l ...

  4. 再读苹果《Threading Programming Guide》笔记(二):线程配置与Run Loop

    本文为再读苹果<Threading Programming Guide>笔记第二篇,作者付宇轩表示:如今关于iOS多线程的文章层出不穷,但我觉得若想更好的领会各个实践者的文章,应该先仔细读 ...

  5. NSThread Run Loop

    2019独角兽企业重金招聘Python工程师标准>>> 前言 多线程的价值无需赘述,对于App性能和用户体验都有着至关重要的意义,在iOS开发中,Apple提供了不同的技术支持多线程 ...

  6. run loop详解

    不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件 ...

  7. Objective-C之run loop详解

    做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一门语言还是需要深层次的了解它,这样才能在使用的时候得心应手,出 ...

  8. iOS多线程开发(三)---Run Loop(一)

    Run Loop Run Loop就是一个事件处理的循环,用来不停的调动工作以及处理输入事件.使用Run Loop的目的就是节省CPU效率,线程在有工作的时候忙于工作,而没工作的时候处于休眠状态. 一 ...

  9. ios跨线程通知_iOS多线程开发(三)---Run Loop(一)

    Run Loop Run Loop就是一个事件处理的循环,用来不停的调动工作以及处理输入事件.使用Run Loop的目的就是节省CPU效率,线程在有工作的时候忙于工作,而没工作的时候处于休眠状态. 一 ...

最新文章

  1. apache配置虚拟主机(virtual host) 笔记
  2. MFC中Spin control的使用
  3. linux 批量创建用户和删除用户
  4. J2ME 模拟短信发送界面开发程序
  5. 图解DotNet框架之三:System.IO
  6. 对携程处理结果表示满意
  7. vs多项目模板及add-in开发
  8. pixmap和label设置图片自适应大小
  9. java自定义生成js代码_基于JavaScript的代码自动生成工具
  10. 软件工程:可行性分析,需求分析思维导图
  11. 建筑模式语言(美)c.亚历山大.pdf,建筑模式语言:城镇·建筑·构造(上下)两本 精装32开,有少量画线...
  12. 雷军做程序员时写的博客,有点东西!
  13. python删除重复单词_Python - 过滤重复的单词
  14. 【超实用的浏览器插件】目前Google Chrome最好用的插件,为什么你还在犹豫不决?
  15. selenium firefox 启动报错 Timed out wating 45 seconds for firefox to start
  16. python画xy轴_用python建立两个Y轴的XY曲线图方法
  17. matlab求解不等式方程组解集,matlab求不等式方程组的可行解
  18. 史上最暖2月谁制造?
  19. 北漂生活第十九弹-再谈留在大城市的一张床还是小城市的一套房
  20. ROS中使用CloudXNS的DDNS功能

热门文章

  1. 数万字的0基础React知识大纲一定要藏藏好
  2. 前端学习(3219):对props进行限制
  3. 前端学习(3168):react-hello-react之...扩展运算符
  4. 前端学习(2938):vue对象之间的实例属性ref
  5. 前端学习(2931):vue里面的虚拟dom和算法
  6. 前端学习(2912):MvvM的实现原理
  7. PS教程第二课:PS安装
  8. [css] 请描述margin边界叠加是什么及解决方案
  9. 工作147:外部that
  10. 工作37:账号绑定逻辑复杂