美文网首页iOS进阶
08.1-Runloop的实际应用场景

08.1-Runloop的实际应用场景

作者: 光强_上海 | 来源:发表于2020-06-21 17:58 被阅读0次

我们在平时开发过程中涉及到runloop相关的应用场景大致有如下几种:

  • NSTimer创建的定时器在滑动过程中失效
  • 控制线程的生命周期
  • 多线程
  • AutoreleasePool释放对象
  • ...

我们先来验证NSTimer创建的定时器,在滚动ScrollView时,定时器就会停止工作的问题,示例代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    static int num = 0;
    [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"-----%d",num ++);
    }];
}

我们在当前控制器View上添加一个UITextView控件,然后在viewDidLoad函数中创建一个定时器,当我们运行项目,定时器可以正常的工作,打印结果如图:

image

当我们滚动UITextView时,发现定时器打印就停止了,如图:

image

这是因为当没有ScrollView滚动事件时,此时的runloop模式为默认模式kCFRunLoopDefaultMode,当我们滚动ScrollView时,这时runloop的模式就由kCFRunLoopDefaultMode切换为UITrackingRunLoopModeUITrackingRunLoopMode只处理滚动相关的任务,所以此时的NSTimer定时器就失效不能正常工作了,那我们怎么处理即可以让Timer能正常工作,又可以滚动TextView尼?

这时我们可以切换当前runloop的模式,将kCFRunLoopDefaultMode改为kCFRunLoopCommonModes模式,代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    static int num = 0;
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"-----%d",num ++);
    }];
    
    // 将kCFRunLoopDefaultMode改为kCFRunLoopCommonModes
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

从打印可以看出,当我们滚动UITextView时,Timer定时器还是可以正常的工作

image

关于NSTimer在runloop中的运用,还有一点需要注意,这时我们换一种创建Timer的方式,代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    static int num = 0;
    NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"---%d", num ++);
    }];    
}

此时我们发现,使用timerWithTimeInterval:方式创建的Timer,运行项目发现定时器不工作,而使用scheduledTimerWithTimeInterval:方式创建的Timer,直接运行项目Timer是可以正常的工作的,这又是因为什么?

系统提供的两种创建Timer的方式:

/// Creates and returns a new NSTimer object initialized with the specified block object. This timer needs to be scheduled on a run loop (via -[NSRunLoop addTimer:]) before it will fire.

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
/// Creates and returns a new NSTimer object initialized with the specified block object and schedules it on the current run loop in the default mode.

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

我们从上面两种创建Timer的官方文档注释中可以看出,scheduledTimerWithTimeInterval:是经过定制化的,此函数创建出来的Timer已经自动添加到当前的runloop中了,并且是在默认的模式下的,而timerWithTimeInterval:创建出来的Timer并没有自动添加到runloop中,需要开发者手动创建runloop并将timer添加到runloop中timer才可以正常运行,我们修改代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    static int num = 0;
    NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"---%d", num ++);
    }];
   
    // 创建一个runloop,并将timer添加到创建的runloop中
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

我们再次运行项目,发现此时timer就可以正常运行了,并且我们滚动TextView也可以正常打印而不会导致timer停止工作

讲解示例Demo地址:https://github.com/guangqiang-liu/08.1-RunloopDemo2

更多文章

相关文章

  • 08.1-Runloop的实际应用场景

    我们在平时开发过程中涉及到runloop相关的应用场景大致有如下几种: NSTimer创建的定时器在滑动过程中失效...

  • Rxjava实际应用场景

    Scheduler线程切换——eg:后台线程取数据,主线程展示 CheckBox状态实时更新 输入框改变即网络请求...

  • RabbitMQ实际应用场景

    场景1:在对商品增删改查的时候发送消息 1、新增/修改商品后台数据库信息2、数据库修改后,发送商品id消息到消息队...

  • Runtime的实际应用场景

    这里只呈现实际的应用场景,demo 已经传到github1.动态给分类添加属性2.方法的交换swizzling3....

  • RunLoop -- 相关问题的总结

    1、RunLoop在实际场景的应用 RunLoop -- 在实际开发中的应用 2、RunLoop内部实现逻辑 Ru...

  • 统计模型实际应用场景

    参考常用统计模型: 决策树&回归&K均值聚类&因子分析分别对应数据分析的思路:分类,回归,聚类,降维。 1 决策树...

  • Runtime实际应用场景详解

    目录 1.给分类增加属性2.方法添加和替换和KVO实现3.weak 释放 nil 的过程4.消息转发(热更新)解决...

  • (三) runLoop 的实际应用场景

    目录 一 . NSTimer 1. 从 timer 的创建方式了解 timer 是否被添加到 runLoop 2....

  • RxJava + Retrofit 的实际应用场景

    介绍 关于RxJava Retrofit很多篇文章都有详细的说明,在这里我想分享一个具体的使用案例,在我的开源项目...

  • RFID在整车物流管理中的应用模式与设备选型

    根据RFID标签的具体应用场景,可以将RFID系统的应用分为两种应用模式。对于应用模式的选择,应当根据实际场景环境...

网友评论

    本文标题:08.1-Runloop的实际应用场景

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