最近公司项目不是很忙,所以想着自己该学习一波了。翻看了存货发现这个这个视频早就放到网盘了但是一直都没看,所以赶紧看了看,受益匪浅,现在整理一下笔记,以备不时之需。
重点说一下Run Loops 在Cocoa中的使用场景:
1.NSTimer
:完全根据runloop封装,没有runloop的话NSTimer完全就是一条废汪。默认情况下开启一个定时器就默认放到runloop下去跑,
2.UIEvent
:事件从产生到分发都是由runloop执行。
3.Autorelease
:自动释放机制也是在runloop中执行
4.NSObject(NSDelayedPerforming)
:
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
5.NSObject(NSThreadPerformaAddition):
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array
常用的几种延时函数之一也是通过runloop机制执行
6.CADisplayLink
:每画一帧动画就会有一个回调(我记得在哪看过说CADisplayLink
定时器的精度会高于NSTimer
,不过我这个渣渣没有用过CADisplayLink
)可能就是因为默认情况下NSTimer会有被中断的风险所有精度不好
7.CATransition、CAAnimation
转场动画,UI动画都会在runloop里去跑,类似于定时器的功能
8.AFNetworking
:(下面有详细介绍)
9.dispatch_get_main_queue()
:(下面有详细介绍)
调用顺序 :
start(dyId)
把程序调用起来 -> main
函数调用了UIApplicationMain
函数 -> GSEventRunModal(Graphics Services)
处理硬件输入(点击等 所有的UI事件都是他发出来的) -> RunLoop层 -> 应用层。
一个线程里可以有多个runloop,一个Runloop可以有多个RunloopMode但是必须为嵌套结构,主线程默认开启,子线程默认关闭,所以他俩是一对一的关系。RunLoopMode 和下面的三种model是树枝形结构都在mode内部。里面是数组结构往里添加。
我们初级渣渣最常用的mode啦,其他的多为系统内部使用,平时应用开发过程中基本上用不着
重点是Mach port驱动轻量级进程间通信方式,某个进程往port发消息,其他进程监听这个端口就能收到消息(貌似都是这个套路啊)
类似于代理,例如7种状态CAAnimation动画在beforeWaiting 和AfterWaiting中执行以上三种使用场景就是最基础最核心的三种mode,个人认为普通开发者最常用的就是第一种
四种RunLoop启动方式,稍微有点基础知识的人应该都知道啦
NSDefaultRunloopMode
:默认状态,空闲状态,开启定时器时如果不特殊指定默认就是使用这种mode执行。UITrackingRunLoopMode
:滑动ScrollView时调用,特别为防止滑动时降低卡顿而设置,默认情况下此状态下定时器就停了,例如滑动微信聊天记录时GIF动画就停止了。UIInitalizationRunLoopMode
:私有,APP启动时使用,这算系统级别的mode不是我们普通人能用的。NSRunLoopCommonMode
:Mode集合比如你有一个特别重要的定时器,即使牺牲滑动效果也必须保留,那你可以选用此种mode 他可以兼顾NSDefaultRunloopMode
与UITrackingRunLoopMode
例如见下图面试热门问题:
Autorelease Pool
什么时候释放?简单说是在RunLoop执行完前检测到可以释放
Autorelease
对象了再进行释放,所以释放时机不会是实时的,其中的原理如上图所示。RunLoop会维护一个栈,先将Autorelease
对象push进去,当检测到需要pop的时候会在RunLoop轮询完前进行释放了
UIKit框架偷偷干了这个工作,有新的RunLoop会push进去,停掉之前的mode 再开始新的mode,当新的结束完了再pop出去,然后再执行上一个。在执行新的mode的时候,上一个mode会停止mode只有一个或者嵌套的关系,在这不存在嵌套关系。
虽然GCD 与 RunLoop 部分功能类似,但是他俩没有啥子关系,GCD的定时器啥的与Runloop一样都是都是系统维护的,唯一有关系的就是
dispatch_get_main_queue()
与Runloop 获取主线程是一致的,因为程序的主线程只能有一个,不能不同,还有dispatch_get_main_queue()
在屌起主线程的时候是在Runloop下执行的。
经过提前的说明,这个伪代码现在很好看懂了,对于粗略了解原理来说简直就是福音,不过细节的话还得看真正源码
这个很好理解,为了节省资源避免频繁创建释放线程耗费资源,AFN会有创建一条常驻线程,然后所有的网络都是异步的有这个专用线程执行。
以下几种是不同的应用,我这才疏学浅没太完全消化也不太好直接写,可以先慢慢看,之后分析。。。