Runloop(上篇)

来源:互联网 发布:excel无法粘贴数据 编辑:程序博客网 时间:2024/05/29 15:28

每个技术的出现都是伴随着解决某个问题而出现的

Runloop   跑圈er (do...while...)

遇到的问题:

1. 当scrollView滑动的时候,同页面上的定时器为何会暂停

2. 如何在tableView滑动时延迟加载图片为提高流畅度

那么这个时候Runloop出现了:

是什么?

一种让线程随时处理事件但不退出的 [机制]

本质上就是一个do-while循环,只要条件满足,就会不停循环,进而程序一直保持运行状态

( 实际上每个程序的入口main函数的确应该那几行代码执行完后程序就结束了,但是UIApplicationMain()会创建主线程,主线程内部会主动开启一个Runloop,因此我们就能见到程序可以长时间保持活跃状态)

为什么?

为什么程序运行伴着Runloop一直这样循环,不会影响性能?答:Runloop管理事件/消息,让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒

详细:

Runloop相关的API:

CFRunLoopRef:CoreFoundation框架内的,基于C语言

NSRunLoop:      CFRunLoopRef的进一步封装,面向对象


CFRunLoopRef分析:

在CoreFoundation框架内关于RunLoop有5个类

CFRunLoop  [                    ]  Ref     就是RunLoop   提供CFRunLoopGetMain()和CFRunLoopGerCurrent()

CFRunLoop  [    Mode       ]  Ref      RunLoop运行模式

CFRunLoop  [    Source    ]  Ref      RunLoop里面内容     【事件源,输入源】

CFRunLoop  [    Timer      ]  Ref       RunLoop里面内容     【定时器】

CFRunLoop  [  Observer  ]  Ref       RunLoop里面内容     【观察者】


一个RunLoop里可以有多个mode,每个mode可以有多个source、timer、observer

但是,每次RunLoop只能置顶一个mode运行。如果想要切换mode,就必须先退出RunLoop,然后重新指定mode运行。为了避免mode之间相互影响。


CFRunLoop  [    Mode       ]  Ref

分成5种mode(创建RunLoop时系统默认注册这5种)

[ kCFRunLoop ] DefaultMode / NSDefaultRunLoopMode               默认mode   主线程在这个mode下运行

UITracking [ RunLoopMode ]                  追踪mode   保证scrollView滑动顺畅不受其他mode影响

UIInitialization [ RunLoopMode ]               启动程序后的过渡mode   启动完成后就不再使用

GSEventRecerve [ RunLoopMode ]               Graphic相关事件的mode   一般用不到

[ kCFRunLoop ] CommonModes                 占位用的mode   作为标记kCFRunLoop ] DefaultModeUITracking [ RunLoopMode ]  用


当scrollView滑动的时候,同页面上的定时器为何会暂停?

当用


1
func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Swift.Void) -> Timer

创建一个timer时,系统会默认把timer添加到[ kCFRunLoop ] DefaultMode 模式中,但是当页面滚动时,RunLoop的mode会自动切换成UITracking [ RunLoopMode ]  模式,因此timer失效,当停止滑动,RunLoop又会切换回NSDefaultRunLoopMode模式,因此timer又会重新启动了。



如何在tableView滑动时延迟加载图片为提高流畅度

把加载图片放入 NSDefaultRunLoopMode 模式中就可以啦。

1
[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"abc"] afterDelay:2.0 inModes:@[NSDefaultRunLoopMode]];






0 0