RunLoop总结以及常驻线程
2019-05-09 本文已影响0人
天明天
一. RunLoop 总结
1. RunLoop 基础
-
RunLoop
就是一个运行循环,每一条线程对应其惟一的RunLoop对象。 -
RunLoop
保存在一个全局的Dictionary里面,线程作为 key, RunLoop 作为Value。 - 子线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它是创建。主线程的RunLoop 是默认启动(创建)的。
-
RunLoop
会在线程结束时销毁。
2. RunLoop访问
- 有两套API可以访问
Runloop
一个是Core Foundation
框架的C语言APICFRunLoopRef
对象。另一个是Foundation
框架 OC 语言NSRunLoop
对象。 -
NSRunLoop
是对CFRunLoopRef
一层OC封装。同样它的访问、运行都有两套API。获取当前线程的RunLoop以及获取主线程的RunLoop:
// Foundation 框架
[NSRunLoop currentRunLoop] ; //当前线程的RunLoop
[NSRunLoop mianRunLoop]; //主线程的RunLoop
// Core Foundation 框架
CFRunLoopGetCurrent() ; //当前线程的RunLoop
CFRunLoopGetMian(); //主线程的RunLoop
-
CFRunLoop
的主要五个主要类:CFRunLoopRef
CFRunLoopModeRef
CFRunLoopTimerRef
CFRunLoopSourceRef
CFRunLoopObserverRef
3. 关于RunLoop
的运行模式Mode
-
RunLoop
主要有两种Mode,分别是:NSDefaultRunLoopMode(KCFRunloopDefaultMode)
:App的默认模式,通常主线程在这个Mode下运行。
UITrackingRunLoopMode
:界面跟踪 Mode,用于 Scrollview 追踪触摸滑动,保证界面滑动不受其他Mode影响。 - 一个RunLoop 可以包含多种Mode,每一个Mode又包含:source0、source1、timer、observer。实际上RunLoop处理的就是这些Mode 里面的事件。
- 每一种Mode之间互不影响,当前只能运行一种Mode,就是CurrentMode。获取当前RunLoop的运行模式:
CFRunLoopMode mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCyrrent());
4.CFRunLoopObserverRef
当前RunLoop
状态的监听
*RunLoop
的状态:
kCFRunLoopAllActivities
包含以上所有状态。
- 为
RunLoop
添加状态监听
(1) 创建监听者Observer
CFRunLoopObserverCreate(<#CFAllocatorRef allocator#>, <#CFOptionFlags activities#>, <#Boolean repeats#>, <#CFIndex order#>, <#CFRunLoopObserverCallBack callout#>, <#CFRunLoopObserverContext *context#>)
参数说明:CFAllocatorRef
:一般填写默认:CFAllocatorGetDefault()
CFOptionFlags
: 监听的状态:监听所有的话填写kCFRunLoopAllActivities
CFIndex
: 顺序:填写0
Boolean
: repeats 是否重复监听YES
CFRunLoopObserverContext
: 填写NULL
CFRunLoopObserverCallBack
: 监听回调,RunLoop状态变化会调用此函数,C语言函数。类型为:
typedef void (*CFRunLoopObserverCallBack)(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);
(2).添加监听者:
CFRunLoopAddObserver(<#CFRunLoopRef rl#>, <#CFRunLoopObserverRef observer#>, <#CFRunLoopMode mode#>)
参数说明:CFRunLoopRef
:当前RunLoop,注意填写C语言
API:CFRunLoopGetCurrent()
CFRunLoopObserverRef
: 填写上面创建的Observer
CFRunLoopMode
:监听模式:kCFRunLoopDefaultMode
最后:
(3)释放监听者
CFRelease(observer);
代码:
CFRunLoopObserverRef observer = CFRunLoopObserverCreate(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, CFRunLoopObserverCallBack callout, NULL);
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
CFRelease(observer);
二. RunLoop 在实际开发中应用
1.控制线程的生命周期(常驻线程,AFNetworking的2.X版本就使用此技术)。
- 我把常驻线程封装了一个类,使用超级简单,可以去我的GitHub 觉得可以就留一个Star。使用方式:
/*
* 运行常驻线程
*/
- (void)run;
/*
* 停止线程
*/
- (void)stop;
/*
* 添加任务 进入线程 串行执行
*/
- (void)addExecuteTask:(ResidentTask)task;
1.实例化线程对象并运行run
:
self.myThread = [[CXMResidentThread alloc] init];
[self.myThread run];
2.把耗时操作传给Block
[self.myThread addExecuteTask:^{
// [NSThread sleepForTimeInterval:3];
}];
3.在想结束常驻线程时 调用stop
-(void)dealloc{
//终止线程
[self.myThread stop];
}
注意这个常驻线程只能处理 串行任务。
2.解决NSTimer 在滑动时失效问题
解决NSTimer 在滑动时停止工作问题,定时器失效问题。原因:Runloop 同一时间只能运行一种模式,UItrackingRunloopMode
与NSDefaultRunloopMode
包含两者的模式:NSRunloopCommonModes
NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
}];
[[NSRunloop currentRunloop] addTimer: timer forMode:NSRunloopCommonModes];//通用模式,是上面两个的集合
3.监控应用卡顿
待完善
4.App性能优化
待完善