一、NSRunLoop的理解
 
     在初学C语言编程的时候,经常会写一种控制台中的程序,程序启动黑色的输入框,等待用户的输入,输入一组数据之后程序继续往下执行程序在等待用户输入数据时会阻塞,这是一种最简单的单线程程序执行的模式。这种简单的编程模型在实际的应用中很难满足用户的需要,比如ios中的app的主线程需要同时响应多种消息,用户触摸事件、timer定时器到时、其它线程发送过来的消息,很自然可以想到为了都能处理到这些消息,那么就在一个while循环中,循环遍历处理这些不同是事件(source),这就是runloop的雏形,也是runloop的含义。
    
     runloop的作用是不是只是简单的循环遍历处理事件呢,当然没那么简单了。首先不同的事件的优先级别是不一样的,用户触摸事件一般高于其它事件类型的,这也是ios系统体验比安卓流畅的一个原因,在一个时间段内主线程收到不同的消息时,runloop优先处理用户交互产生的事件。当然,要达到这种效果,就需要将source分成不同的类型,并把这些类型对应不同的模式(NSRunLoopMode),在某种模式下面只处理指定的几种事件,比如一个UItableView在滑动的时候,主线程的RunLoop会在NSRunloopTrackingMode模式下面运行,这个模式下面是不会处理timer消息的,这样保证在滑动的时候,runloop能一直处理滑动的消息,不停的滑动不停的刷新界面,保证界面的流畅度。
 
     可以想像出来,runloop就类似于一个消息泵,每种事件(source)到达的时候,会在对应的类型的事件队列下面排队,runloop运行在不同模式时从不同的队列中取出消息进行执行,就如下图:
     右边是不同的事件,左边是一个线程中的runloop。那么runloop在一个循环时,就会对应不同的状态,runloop开始,runloop结束,此外还可以想到runloop正在等待消息。对应到真正的类型如下:
    
 
     依次代表的含义是,进入runloop,将要处理timer消息,将要处理其它类型的消息,将要进入等待,结束等待,退出几种含义。
     
二、RunLoop的实现
     
     Runloop的源代码没有真正的源代码,只有找到替代实现cocotron,里面有Runloop的实现,看了之后对Runloop会有更多理解。Runloop是否真的是while循环实现的呢,猜测应该不是,隔一段时间遍历检测这样的效率太低了,类似于poll,需要遍历所有的事件,没有事件响应进入休眠,有事件遍历检测,这样不停休眠唤醒。其实还有更高效率的实现,类似于epoll,在内核中注册事件的回调,需要内核支持。runloop是不是这样实现的不得而知。
 
     官方文档说Runloop是每个线程独有的,可以猜测出Runloop是每个线程结构中的一个对象,只是没有进入running的状态,主线程会默认跑起来。NSTimer需要加入到RunLoop中才会生效,因为是runloop中响应timer消息,想想如果一个Runloop没有跑起来加入一个timer是不会有什么反应的。
 
三、RunLoop的利用
     
     有很多场景下面,我们需要对app的性能进行优化,比如一个滑动列表,我们需要优化FPS,那么我们需要保证在滚动的过程中,主线程不要做多余的事情,比如读取大的图片文件,比如渲染大涨图片,这些都会产生卡顿,有一种场景是,用户下载一张图片,通过通知(同步的方式)的方式告知cell下载成功进行刷新,如果table在滚动的过程中收到这个通知,那么就会对图片进行渲染,图片尺寸小点没关系,大点的图片将会产生卡顿。有没有办法在滑动停止,或者runloop空闲的时候执行某些消息呢?
     下面是我的一种实现,可以下载源代码进行阅读,通过performSelector的方式,将要执行的selector转化成invocation放入队列中,同时检测runloop的状态,空闲的时候再进行执行。
     实际上系统已经考虑到这个场景了,有一种runloopmode是NSConnectionReplyMode,指的是在收到网络回包通知时在这种mode下面响应,而现在大量使用第三方类库的时候没有考虑这个机制。
 
四、RunLoop带来的坏处
     
     我们知道performSelector是在Runloop中响应的,在一轮循环中执行某个selector,这个时候如果在selector中发生了crash,那么会经常看到调用堆栈的上层只是Runloop相关的内容,很难判断出一个是哪里调用的selector。不知道是否有人对此研究,是否可以对调用层进行跟踪。
 
     

NSRunLoop的利用的更多相关文章

  1. NSRunLoop的进一步理解

    iPhone应用开发中关于NSRunLoop的概述是本文要介绍的内容,NSRunLoop是一种更加高明的消息处理模式,他就高明在对消息处理过程进行了更好的抽象和封装,这样才能是的你不用处理一些很琐碎很 ...

  2. NSRunLoop详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执行和休眠,在有事情做的时候使当前NSRunLoop控制的线程工作,没有事情做让当前NS ...

  3. NSRunLoop 概述和原理

    NSRunLoop 概述和原理 1.什么是NSRunLoop? 我们会经常看到这样的代码: - (IBAction)start:(id)sender { pageStillLoading = YES; ...

  4. 利用RunTime解决由NSTimer导致的内存泄漏

    NSTimer使用场景 用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图,使用NSTimer实现这个功能很简单代码如下 NSTimer *_timer; _timer = [N ...

  5. 第四十三篇、利用NSProxy解决NSTimer内存泄漏问题

    问题描述: 用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图.如果我们在 timerWithTimeInterval:1 target:self 中指定target为当前控制器 ...

  6. 关于NSRunLoop和NSTimer的深入理解

    一.什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在于有事情做的时候使的当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠 NS ...

  7. NSRunLoop原理详解——不再有盲点

    编程最怕的就是有盲点,不确定,而runloop官网对其提及的又很少:那么看完这篇应该使你有底气很多~ RunLoop整体介绍 An event-processing loop, during whic ...

  8. 利用GCD 中的 dispatch_source_timer 给tableViewCell添加动态刷新的计时/倒计时功能

    1.思路一(失败) 在设置好cell 里的内容之后在每个cell 返回时调用定时器事件,更新cell 内容,然后刷新整个表格. - (void)didadida:(UITableViewCell *) ...

  9. 利用NSProxy解决NSTimer内存泄漏问题

    之前写过一篇利用RunTime解决由NSTimer导致的内存泄漏的文章,最近和同事讨论觉得这样写有点复杂,然后发现有NSProxy这么好用的根类,根类,根类,没错NSProxy与NSObject一样是 ...

随机推荐

  1. [SOJ]Easy sort (归并排序)

    Description You know sorting is very important. And this easy problem is: Given you an array with N ...

  2. 隐藏android中EditText中的下划线以及修改光标颜色

    在android开发中 EditTextText是我们经常用到的,我们使用时会有一些小问题,当我们点击输入文字时,EditText中的光标和下划线会变成粉红色. 解决方法很简单,我们只要在EditTe ...

  3. mysql 查看数据库中所有表的记录数

    use information_schema; SELECT DISTINCT t.table_name, t.engine '表引擎', t.table_rowsFROM TABLES tWHERE ...

  4. pack://application:,,,/

    FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid)); gridFactory.SetValu ...

  5. 在vim编辑器中,删除操作

    我这里在编辑一个很大的文件,有几万行,都是文件名sheetid, 中间有很多空行,我现在要做的事情就有要把这个文件中的空行都删除掉,这个本来想在ultraedit里面完成的,结果弄了好半天都没有搞定, ...

  6. WebForm 文件上传

    //Button1的点击事件 //FileUpload1.FileName为所传文件的名字. //以DateTime.Now.ToString("yyyyMMddhhmmssms" ...

  7. 让webstorm支持新建.vue文件

    1. 首先安装vue插件,安装方法: file-->setting  -->  plugin  ,点击plugin,在内容部分的左侧输入框不用输入任何东西,直接点击下图中的按钮. 如下图所 ...

  8. Web流量劫持

    BadTunnel实战之远程劫持任意内网主机流量 http://www.freebuf.com/articles/web/109345.html http://blog.csdn.net/ts__cf ...

  9. WPF 命令的简单总结

    WPF的命令Command主要解决的问题,就是代码复用.一个很重要的应用意义,在于它将很多地方需要的调用的相同操作,以统一的方式管理,却又提供了不同的访问结果. 举个例子来说,我可能通过“点击butt ...

  10. Linux_jdk

    先查看下 yum list java* yum install java-1.7.0-openjdk* -y 环境变量应该是会自动配置的 或者手动配置编辑/etc/profile #vi /etc/p ...