NSTimer 与 Run loop Modes

一.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游戏软件提示d3dcompiler_43.dll的五个解决方法,亲测靠谱

在使用电脑进行工作,玩游戏的时候,我们常常会遇到一些错误提示,其中之一就是“D3DCompiler_43.dll丢失”的提示。D3DCompiler_43.dll是一个非常重要的动态链接库文件。它是由DirectX SDK提供的,用于编译和优化DirectX着色器代码的…

php需要掌握什么,php专业需要掌握哪些知识

网站我们分为前端、后端,组成在一起就可以搭建一套独立的网站。在招聘职位中,前端和后端是分开来招聘的,有前端设计师,PHP后端工程师。如果你能独立完成一个网站,那就是全栈工程师了。好了,让我们来看看搭建…

前端学习(582):实现观看和调试dom节点

1双击编辑修改 2修改dom 右击edit as html 3复制粘贴

无法打开用户默认数据库,登录失败,用户‘sa’登录失败,错误:4064的解决方法...

无法打开用户默认数据库,登录失败,这是因为登录帐户的默认数据库被删除。解决方案:用windows身份模式进入,选择“安全性”---"登录名"------“HRKJ”,在HRKJ上右击,弹出如图窗口,找到…

前端学习(584):在dom中调试节点

第一种方式 修改完成 第二种 删除标签 执行 第三种 执行 删除

php订阅系统,php redis pub/sub(Publish/Subscribe,发布/订阅的信息系统)之基本使用

一.场景介绍最近的一个项目需要用到发布/订阅的信息系统,以做到最新实时消息的通知。经查找后发现了redis pub/sub(发布/订阅的信息系统)可以满足我的开发需求,而且学习成本和使用成本也比较低。二.什么是redis pub/sub资料查看大家在看我的blog的同时可以打开redis…

SQL Server 自定义函数 返回树结构函数

数据库结构: 表内的数据: 自定义函数: 递归查出 树下所有节点 ,参数是 父idcreate function sss(id as int)returns t table(id int not null,name int not null,pid int null)asbegindeclare lay as int;insert into t select * from tree where pid id;select lay min(id) …

php 生成器作用,php 生成器的理解和使用

image.png开头介绍的这个文章总结的很详细,而且大多的介绍其实都是这么写的,也是这些例子。但是手册的介绍也很重要。此处,我主要写一些个人的理解要点1.生成其是一种更容易实现简单对象迭代。所以他的本质其实是相当于有助于更好的实现 fore…

哪里学php开发,哪里学web开发

在开始学习Web开发时,我建议做的第一件事就是确定明确的最终目标,并牢记其中。也许你想改变职业生涯。也许你对应用程序有一个邪恶的想法。或许你只是想学习乐趣。无论您的目标是什么,了解您为什么这样做都很重要。这种理解将帮助您提高学习时…

前端学习(590):调试javascript的流程

vs 安装live server插件 第一种方式 第二种方式 使用alert 断点调试debugger 断点调试 断点调试 设置断点

统一管理MOSS2010用户头像

我们都知道MOSS 2010里面的“我的网站”里面有一个上传照片功能,通过那里用户可以方便的上传自己的照片。也可以通过在AD里面上传用户的头像,通过MOSS的 User Profile Service Application 服务进行同步,实现MOSS,Outlook,Lync 头像的统一管理…