美文网首页
RunLoop总结以及常驻线程

RunLoop总结以及常驻线程

作者: 天明天 | 来源:发表于2019-05-09 19:53 被阅读0次

一. RunLoop 总结

1. RunLoop 基础
  • RunLoop就是一个运行循环,每一条线程对应其惟一的RunLoop对象。
  • RunLoop保存在一个全局的Dictionary里面,线程作为 key, RunLoop 作为Value。
  • 子线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它是创建。主线程的RunLoop 是默认启动(创建)的。
  • RunLoop会在线程结束时销毁。
2. RunLoop访问
  • 有两套API可以访问 Runloop 一个是 Core Foundation框架的C语言API CFRunLoopRef 对象。另一个是 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的状态:

屏幕快照 2019-05-09 下午6.04.42.png
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 同一时间只能运行一种模式,UItrackingRunloopModeNSDefaultRunloopMode 包含两者的模式:NSRunloopCommonModes

NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        
    }];
[[NSRunloop currentRunloop]  addTimer: timer forMode:NSRunloopCommonModes];//通用模式,是上面两个的集合
3.监控应用卡顿

待完善

4.App性能优化

待完善

相关文章

网友评论

      本文标题:RunLoop总结以及常驻线程

      本文链接:https://www.haomeiwen.com/subject/bjnwoqtx.html