RunLoop总结

2018-03-05  本文已影响14人  黑化肥发灰

什么是RunLoop

Runloop视频
这个视频讲得很好,看完收获很大,对RunLoop有概念了,并且了解了一些应用。尤其是前面那个子线程timer的例子,一步一步递进,容易理解,建议多看几遍。
从这个例子开始了解,创建计时器:
主线程添加计时器

主线程添加计时器
上面的scheduledTimerWithTimeInterval是对下面的封装。是添加到NSRunLoop的默认模式,还是要用下面的方式创建加timer。

子线程添加计时器

CFRunLoopRun的伪代码 Runloop培训视频有讲解
两小时二十五分钟开始听比较好。

__CFRunLoopRun {
    do {
        __CFRunLoopDoBlocks 处理 block
        __CFRunLoopDoSources0 处理 source0
        if (判断是否有其他消息需要处理,如果有) {
            goto: handler_msg(处理消息模块)
        }
        __CFRunLoopServiceMachPort(wait) 准备休眠 阻塞 // 如果有消息来了,需要处理就醒了
       handle_msg: (处理消息模块:timer, gcd, __CFRunLoopDoSource1)

    } while(1)
}

从字面上看

基本作用

存在价值

没有RunLoop
有RunLoop
主运行循环

RunLoop 对象

RunLoop 与多线程

获取 RunLoop 对象

[NSRunLoop currentRunLoop];  // 获取当前线程的 RunLoop 对象
[NSRunLoop mainRunLoop]; // 获得主线程的 RunLoop 对象
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop 对象
CFRunLoopGetMain();  // 获得主线程的 RunLoop 对象

RunLoop相关类

注:RunLoop如果没有这些东西,会直接退出

RunLoop 应用

1. 常驻线程

应用场景:经常在后台进行耗时操作,比如:监控联网状态,扫描沙盒等,不希望线程处理完事件就销毁,保持常驻状态。
第一种

// 开启
- (void)run
{
// addPort: 添加端口(就是source)forMode: 设置模式
    [[NSRunLoop currentRunLoop] addPort: [NSPort port] forMode: NSDefaultRunLoopMode];
// 启动RunLoop
    [[NSRunLoop currentRunLoop] run];

 /*
  //另外两种启动方式
    [NSDate distantFuture]:遥远的未来  这种写法跟上面的run是一个意思
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    不设置模式
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
  */
}

// 退出当前线程
[NSThread exit];

2. NSTimer (最常见 RunLoop 使用)

- (void)timer
{
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    // 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

    // 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

    // 定时器会跑在标记为common modes的模式下
    // 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode兼容
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- (void)timer2
{
    // 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
 
    // 修改模式
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

UITableView 滚动时模式由 NSDefaultRunLoopMode 进入 UITrackingRunLoopMode,NSTimer 不再响应。NSRunLoopCommonMode模式下两种模式都可运行。

3. 自动释放池

参见参考文章

main里面有个死循环就是RunLoop循环
目的:

  1. 保证程序不退出;
  2. 负责监听事件,触摸(有没有人摸我)、时钟、网络事件(回调);
  3. 如果没有时间发生,会让程序进入休眠状态;
  4. 五种模式,UI模式优先级最高,UI模式只能被触摸事件触发,保证高效。
  5. 一条线程的生命只能通过任务保住

子线程里面设置定时器,可以看出子线程里面RunLoop需要自己开启,主线程则默认已经开启。直接用while(true)并不能实现触发事件效果。线程的声明需要通过任务保住,所以要将RunLoop开启。
RunLoop是懒加载,只有第一次去拿才会创建。

总结一下


参考文章

https://blog.ibireme.com/2015/05/18/runloop/
深入理解RunLoop
解密-神秘的 RunLoop
(最全)RunLoop 原理+使用场景+面试总结

学习视频

Runloop视频 密码:ztaf
Runloop培训视频

上一篇 下一篇

猜你喜欢

热点阅读