RunLoop五:在实际开发中的应用

一、在实际开发中的应用

  • 控制线程生命周期(线程保活)
  • 解决NSTimer在滑动时停止工作的问题
  • 监控应用卡顿
  • 性能优化

二、控制线程生命周期(线程保活)
在项目中会遇到创建一个子线程去做一些事情。为什么要创建一个子线程去做事情?因为如果把所有的事情都放在主线程中去做,就会阻塞住组线程。导致APP 看起来很卡。这个时候就可以开启一个子线程,把耗时的操作放到子线程中。这样就不会阻塞主线程,APP 开起来不会卡。
子线程做完事情以后,就会销毁。但有的时候,希望子线程昨晚事情以后,不要销毁,当程序员需要的时候才销毁。这个时候就可以使用 RunLoop 控制子线程的生命周期。
这种做法也叫做线程保活(保住线程的命)。

三、解决NSTimer在滑动时停止工作的问题
(一)、为什么 NSTimer 不能再滚动 UIScrollView时保持开启状态

  • 默认情况下,在滚动 tableView、UIScrollView 的时候。NSTimer会停止工作。

  • 创建一个 UITextView, UITextView 是 UIScrollView 的子类。使用它来演示 NSTimer 在滑动时停止工作的问题

  • 写一个 定时器代码,每隔一秒钟打印一次
    定时器代码,每隔一秒钟打印一次

  • 当滚动 UITextView 的时候,定时器停止打印。这是因为 混动 UITextView 的时候,RunLoop 会进入另一个Mode 模式UITrackingRunLoopMode 下.

  • 当在UITrackingRunLoopMode模式下,定时器会停止。

  • 当不在滚动 UITextView , 定时器会重新开始。
    在这里插入图片描述

  • 这是因为 RunLoop 同一时间,只能运行一种模式。当滚动UITextView 的时候,定时器会停止。说明这两个模式不一样。也就是说 NSTimer 不是 UITrackingRunLoopMode 模式。

  • NSTimer 是在默认模式下工作的。kCFRunLoopDefaultMode模式

  • 也可以使用 CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent()) 打印一下当前的 模式

注:

  • kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行
  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

(二)、让 NSTimer 在 滚动 UIScrollView时也可以滚动

  • 方法[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) { ... ... }]; 会直接把定时器添加到 默认mode中
  • 方法 [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) { ... ... }]; 只是返回一个 NSTimer 中。没有添加到 runloop 中.
  • [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 把 timer 添加到 runloop 中。 forMode 后面可以添加三种:
    • NSDefaultRunLoopMode : 默认模式
    • UITrackingRunLoopModes: UIScrollView 的那种模式
    • NSRunLoopCommonModes: 通用模式 。
      • 它并不是一个真的模式,它只是一个标记
      • 上面的 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 才是 真正存在的模式
      • 传入这个 ,意味着:timer 在设置了 common 标记的模式下都能运行。而 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 都标记成了 Common 。 所以在这两个mode 上都可以使用。

(三)、回顾 RunLoop 的定义

  • RunLoop 的结构

    • 线程(pthread_t _pthread): 一个 RunLoop 有一个线程 。 一对一。
    • 模式(CFMutableSetRef _modes): 里面装着 RunLoop 能用的模式. 有很多个
    • 当前模式(CFRunLoopModeRef _currentMode)
    • CFMutableSetRef _commonModes: 装到这里的模式,意味着标记成了 common 的模式。
    • CFMutableSetRef _commonModeItems: 存放能在_commonModes 下工作的 东西(如刚才的 timer 变量)
  • 当调用 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonMode]; 代码时,它调用的就是 runloop 中的 CFMutableSetRef _commonModes.。

  • 这个common模式下包含 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 这两个模式。

  • 所以 timer 能在 _commonModes 数组中存放的模式下工作。
    RunLoop 的结构

四、监控应用卡顿

五、性能优化

猜你喜欢

转载自blog.csdn.net/M316625387/article/details/83270639