iOS runloop

字数1601 阅读6946 评论8 喜欢113

   写这篇文章开始之前,我都不知道runloop是什么东西,如果从字面的意思翻译应该是一直循环的跑,怀疑可能和死锁有关系,可是死锁具体是怎么回事,我只是记得有这个说法,也发现了一个自己不懂的知识。

初识runloop

   我在网上看了一下@sunnnyxx 关于runloop的视频.了解了一下runloop相关知识,也去网络上看各种关于runloop的讲述。

   我们一般程序就是执行一个线程,是一条直线.有起点终点.而runloop就是一直在线程上面画圆圈,一直在跑圈,除非切断否则一直在运行。网上说的比喻很好,直线就像昙花一现一样,圆就像OS,一直运行直到你关机为止。

   在我们学习iOS生命周期里面都会存在销毁的过程,但是屏幕好像一直能接收各种指令,感觉很像runloop的功效,好像这些是和顶层UIKit无关,IOS架构最底层是Core OS,我分析应该是苹果封装好了,只是我们看不到源码而已。


为什么要使用runloop

@sunnnyxx 在视频介绍了四个作用:

  • 使程序一直运行接受用户输入
  • 决定程序在何时应该处理哪些Event
  • 调用解耦(对于编程经验为0的完全没搞懂这个意思,解释为Message Queue)
  • 节省CPU时间

   这段视频我觉得不太适合小白去看,因为好多概念还没有融会贯通,也没有理解透彻。但是既然看了,就得总结一下,至少产生一个树突先,留下一个问号,未来把问号变成叹号。

   回到开始的疑问,为什么要使用RunLoop,一般情况下我们是没必要去启动线程的RunLoop,除非需要在一个单独的线程长久的检测某个事件,就像视频里面提到的类似微信的语音功能,见一个RunLoop专门负责监听说话的线程。看需求而定了。


CFRunLoopSource

Source是RunLoop的数据源抽象类,类似IOS中的protocol
RunLoop定义两个Version的Source

  • Source0:处理App内部事件,App自己负责管理(触发),如UIEvent,CFSocket
  • Source1:由RunLoop和内核管理,Mach port驱动 如CFMach、CFMessage

CFRunLoopObserver

向内部报告RunLoop当前状态的更改 CAAnimation

RunLoopObserver 与 Autorelease Pool

UIKit通过RunLoopObserver在RunLoop两次Sleep间对AutoreleasePool进行pop和push,将这次Loop中产生的Autorelease对象释放。(好像swift中没有关于释放的问题)

CFRunLoopMode

RunLoop在同一时段只能且必须在一种特定Mode下Run
更换Mode时, 需要暂停当前的Loop,然后重启新的Loop

  • NSDefalutRunLoopMode      默认状态.空闲状态
  • UITrackingRunLoopMode     滑动ScrollView
  • UIInitializationRunLoopMode    私有,App启动时
  • NSRunLoopCommonModes     默认包括上面第一和第二

UITrackingRunLoopMode 与 NSTimer

默认情况下NSTimer被加入NSDefalutRunLoopMode
如果想NSTimer受到组件或者动画影响 添加到NSRunLoopCommonModes(OC代码如下:)

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

swift版代码:

 NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

RunLoopMode切换

NSDefaultRunLoopMode->UITrackingRunLoopMode->NSDefalutRunLoopMode

RunLoop的挂起与唤醒

  • 制定用于唤醒的mach_port端口
  • 调用mach_msg监听唤醒端口,被唤醒前,系统内核将这个线程挂起,停留在mach_msg_trap
  • 由另外一个线程(或另一个进程中的某个线程)向内核发送这个端口的msg后,trap状态被唤醒,RunLoop继续开始干活

AFNetWorking 中创建RunLoop

创建一个常驻服务线程的很好方法

 [[NSThread currentThread] setName:@"AFNetworking"];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefalutRunLoopMode]//一直活着
[runLoop run];

swift版代码

var loop = NSRunLoop.currentRunLoop()
loop.addPort(NSMachPort(), forMode: NSDefaultRunLoopMode)
loop.run()

一个TableView延迟加载图片的新思路

[self.avatarImageView performSelector:@selector(serImage:)    withObjetc:downloadedImageafterDelay:0inModes:@[NSDefaultRunLoopMode]]+ (NSThread *)networkRequestThread {static NSThread *_networkRequestThread = nil;static dispatch_once_t oncePredicate;dispatch_once(&oncePredicate, ^{_networkRequestThread =[[NSThread alloc] initWithTarget:selfselector:@selector(networkRequestThreadEntryPoint:)object:nil];[_networkRequestThread start];});return _networkRequestThread;

}
这个代码无法转换成swift,可能是我没想到办法,大家谁找到了请评论,谢谢了。


让Crash的App回光返照 只针对Signal Crash

CFRunLoopRef runloop = CFRunLoopGetCurrent();
NSArray *allModes = CFBridgingRelease(CFRunLoopCopyAllModes(runLoop));
while(1){for (NSString *mode in allModes){CFRunLoopInMode((CFStringRef)mode,0.001,false);}
}

RunLoop事件队列
每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:

  1. 通知观察者run loop已经启动
  2. 通知观察者任何即将要开始的定时器
  3. 通知观察者任何即将启动的非基于端口的源
  4. 启动任何准备好的非基于端口的源
  5. 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
  6. 通知观察者线程进入休眠
  7. 将线程置于休眠直到任一下面的事件发生:
    • 某一事件到达基于端口的源
    • 定时器启动
    • Run loop设置的时间已经超时
    • run loop被显式唤醒
  8. 通知观察者线程将被唤醒。
  9. 处理未处理的事件
    • 如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
    • 如果输入源启动,传递相应的消息
    • 如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
  10. 通知观察者run loop结束。

异步测试

- (BOOL)runUntilBlock:(BOOL(^)())block timeout:(NSTimeInterval)timeout{   __block Boolean fulfilled = NO;void (^beforeWaiting) (CFRunLoopObserverRef observer, CFRunLoopActivity activity) =^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {fulfilled = block();if (fulfilled) {CFRunLoopStop(CFRunLoopGetCurrent());}};CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, beforeWaiting);CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);// Run!CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false);CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);CFRelease(observer);return fulfilled;

}


总结一下

基本上对于RunLoop,我只能说我只有简单的模糊印象,但是不理解,也不太清楚在现实如何使用,因为实践才能知道如何做,真的在脑里形成了树突,希望在未来搞定,研究透彻。看这些代码时候我发现我的基础知识还需要巩固。感谢不相识的孙源。
声明一点:不要只去收藏,去看看代码有没有问题,知识有没有解释错误的,交流学的更快。

 推荐拓展阅读

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持

 喜欢

113

分享到微博 分享到微信

更多分享

×

喜欢的用户

  •  uchihaItachiF2016.02.16 15:06
  •  离子来了2016.02.15 10:34
  •  徐勇2016.01.29 19:12
  •  忘山老人2016.01.12 11:24
  •  过猫一样的生活2016.01.12 10:44
  •  霸世英豪2015.12.18 11:31
  •  Slyneil2015.11.29 10:24
  •  coding点啥2015.11.28 10:05
  •  剁椒鸡蛋2015.11.25 21:11
  •  然然啊2015.11.08 23:34
  •  ZL_October2015.11.08 14:20
  •  lizi172015.11.03 14:34
  •  到北极去看雪2015.11.01 17:03
  •  迈克学_2015.10.14 22:34
  •  bf226611e6ed2015.09.02 09:27
8条评论 ( 按时间正序· 按时间倒序· 按喜欢排序 )添加新评论

狍子君

2 楼 · 2015.04.04 08:08

不错

喜欢(0)回复

a4975e0f02b0

3 楼 · 2015.04.04 09:12

是iOS而不是IOS。

喜欢(0)回复

小白和小黑

4 楼 · 2015.04.04 09:17

@a4975e0f02b0 好的,已经更改。

喜欢(0)回复

胖子洋

5 楼 · 2015.08.11 13:57

能给出sunnnyxx的视频地址么?谢谢

喜欢(0)回复

半尺尘: @胖子洋 http://v.youku.com/v_show/id_XODgxODkzODI0.html 或者搜索:iOS线下分享《RunLoop》by 孙源@sunnyxx

回复2015.12.10 18:18

 添加新回复

iOS runloop相关推荐

  1. iOS RunLoop基础和应用举例

    文章目录 RunLoop介绍 iOS 中的RunLoop RunLoop应用举例 保证线程的存活 AFNetworking NSTimer 补充说明 参考文档及更多资料 关于autoreleasepo ...

  2. iOS RunLoop详解

    一.简介 CFRunLoopRef源码 RunLoop是一个对象,这个对象在循环中用来处理程序运行过程中出现的各种事件(比如说触摸事件.UI刷新事件.定时器事件.Selector事件),从而保持程序的 ...

  3. ios Runloop

    一.概念:一个Runloop就是一个事件处理的循环,用来不停的调度工作和处理输入事件,使用runloop的目的是让你的线程在有工作的时候处于工作状态,没有工作的时候处于休眠状态. 一般来讲,一个线程一 ...

  4. iOS RunLoop 初识

    今天突然才之间才意识到NSTimer这样的运行方式,是在多线程中实现的循环还是在主线程中去实现的呢.当然不可能是在主线程中的while那么简单,那样什么都干不了,简单看了下NSTimer是以同步方式运 ...

  5. ios runloop学习

    今天突然才之间才意识到NSTimer这样的运行方式,是在多线程中实现的循环还是在主线程中去实现的呢.当然不可能是在主线程中的while那么简单,那样什么都干不了,简单看了下NSTimer是以同步方式运 ...

  6. iOS RunLoop 原理和核心机制

    RunLoop的定义 当有持续的异步任务需求时,我们会创建一个独立的生命周期可控的线程.RunLoop就是控制线程生命周期并接收事件进行处理的机制. RunLoop是iOS事件响应与任务处理最核心的机 ...

  7. iOS - RunLoop 深入理解

    一直不是很了解iOS的runloop机制的具体机制,无意间搜到这个文章,感觉非常详细,收藏了- 作者费不少劲写的,转载请注明出处,谢谢侬.-原文作者:Mitchell 孟晨 于是出处:原文地址 后面我 ...

  8. iOS RunLoop简介

    一.什么是RunLoop? RunLoop是运行循环,每个Cocoa应用程序都由一个处于阻塞状态的do/while循环驱动,当有事件发生时,就把事件分派给合适的监听器,如此反复直到循环停止.处理分派的 ...

  9. ios RunLoop 用法

    2019独角兽企业重金招聘Python工程师标准>>> A run loop for a given thread will wait until one or more of it ...

最新文章

  1. 敏捷原则比敏捷框架更重要
  2. tradingview Vue
  3. 如何快速出稿一个优秀APP的构图
  4. 在objective-C中#pragma mark是什么意思?
  5. 资源放送丨《容灾体系建设之“独孤九式”》PPT视频
  6. java中一个数轮流除去所有数_Java实现A、B两人轮流从盒中取球,取出球的数目必须是:1,3,7或者8个...
  7. 超级卡特兰数(bzoj 4706: B君的多边形)
  8. [转载] Python中NumPy简介及使用举例
  9. mysql慢查询原因_mysql 慢查询的原因分析点滴
  10. matlab 使用,MATLAB使用方法
  11. 新媒体运营胡耀文教程:短视频+怎么变现?一文读懂4大商业模式
  12. eclipse新建java项目报错 jrt-fs.jar
  13. CF833D Red-Black Cobweb 点分治、树状数组
  14. html word 批注,word怎么批注修改文章
  15. 何时是PNE(纯策略纳什均衡)?何时是MNE(混合策略纳什均衡)?
  16. h5模型转化为pb模型,代码及排坑
  17. 如何获取显示器的EDID信息
  18. 假设一个类,继承了父类并且实现了一个接口,然后父类和接口有一个同名的方法,那么此时会发生什么情况,编译会提示出错吗?如果不出错,那么这到底算是重写还是实现接口方法?
  19. 计划任务(啊啊啊啊啊)
  20. 华为P20 如时升Android 9.0,华为P20系列升级EMUI9.0之后简直太流畅太完美!

热门文章

  1. 通过微博名查看id html,微博id在哪里查看?
  2. 群晖服务器主板维修,没那么复杂 群晖DS213j内部拆解
  3. Qt|QToolBtton实现三态图标及文字变化
  4. 《白帽子讲web安全》学习笔记(第一篇)
  5. 栈内存 堆内存 (数据类型间的存储区别)
  6. 线性回归方程b保留几位小数_实验室原始数据怎么保留最准确?(一)
  7. 算法基础17 —— 单调栈(Acwing 830 单调栈)
  8. 杭电ACM 2094 产生冠军——C语言)
  9. 学习ARM开发(11)
  10. 2021韩顺平图解linux