美文网首页NSRunLoopiOS之runloop
NSRunloop简单细说(三)—— 定时器和端口

NSRunloop简单细说(三)—— 定时器和端口

作者: 刀客传奇 | 来源:发表于2017-08-23 14:05 被阅读49次

    版本记录

    版本号 时间
    V1.0 2017.08.22

    前言

    NSRunloopOC Foundation框架中非常重要的一个类,很多时候我们会使用它,但是未必对其有深入的了解,接下来几篇我就会带着大家重新学习一下NSRunloop这个类,从简单到复杂,从基本到深化,我会一步步的走完。希望对大家有所帮助。感兴趣的可以看我上一篇。
    1. NSRunloop简单细说(一)—— 整体了解
    2. NSRunloop简单细说(二)—— 获取运行循环及其模式

    一、- (void)addTimer:(NSTimer *)timer forMode:(NSRunLoopMode)mode;

    这个方法我们经常用,其实就是将定时器加入到runloop中,才能开启定时器。

    下面我们看一下参数:

    • timer :实例化的定时器对象。
    • 添加定时器的模式。 您可以指定自定义模式或使用运行循环模式Run Loop Modes中列出的其中一种模式。

    下面看一个例子

    - (void)demoAddTimer
    {
        NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"A");
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    }
    

    看一下输出结果

    2017-08-23 12:20:57.584335+0800 JJOC[11019:5299493] A
    2017-08-23 12:20:59.584386+0800 JJOC[11019:5299493] A
    2017-08-23 12:21:01.584310+0800 JJOC[11019:5299493] A
    2017-08-23 12:21:03.584310+0800 JJOC[11019:5299493] A
    2017-08-23 12:21:05.584304+0800 JJOC[11019:5299493] A
    2017-08-23 12:21:07.584378+0800 JJOC[11019:5299493] A
    

    还有几点需要注意:

    • 可以向多种输入模式添加定时器。 当以指定模式运行时,接收器使计时器在预定日期到达时或之后触发。 触发时,定时器调用其相关联的处理程序例程,它是指定对象上的选择器。
    • 要从其安装的所有运行环路模式中删除定时器,请向定时器发送无效invalidate消息。
    • 这里定时器加入runloop的模式选择的是NSDefaultRunLoopMode,一般情况下是没有问题的,但是在一些情况下是有问题的,比如说滑动界面定时器停止等,这个解决方法就是更换模式为NSRunLoopCommonModes
    • 还有这个问题,我这里调用的这个方法是ios 10.0以后才有的,所以如果你适配8.0系统的话就不能用这个方法了,应该用+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;这个方法,还有个问题就是如果用上面那个block的方法还要注意循环引用的问题。

    结论:这个很常用,大家需要谨记。


    二、- (void)addPort:(NSPort *)aPort forMode:(NSRunLoopMode)mode;

    该方法的作用就是:将端口作为输入源添加到运行循环的指定模式。其实就是往RunLoop的 Mode 中添加一个source1任务。

    下面看一下参数:

    • aPort:要加入的端口。
    • mode:运行循环模式,还是那几种,前面已经说过了,这里就不多说了。

    我们在AFNetworking中就看到了这个方法的使用,如下所示:

    + (void)networkRequestThreadEntryPoint:(id)__unused object 
    {
        @autoreleasepool {
            [[NSThread currentThread] setName:@"AFNetworking"];
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
            [runLoop run];
        }
    }
    

    这里,开启了一个线程,同时开启runloop,并添加了一个port事件维系runloop 的运行,但是port并不发送时机的消息。这个线程是AFNetWorking用于将NSURLConection置于后台处理请求和回调的。不过现在NSURLConection已经被该框架所废弃了。大家知道这个用法和使用情况就可以了,其实编程思想比代码实现要重要的多。

    下面还要注意:

    • 此方法使用接收器调度端口。 您可以将端口添加到多种输入模式。 当接收器以指定的模式运行时,它会将发往该端口的消息分派到端口的指定处理程序。

    结论:思路很重要,需要大家思考。


    三、- (void)removePort:(NSPort *)aPort forMode:(NSRunLoopMode)mode;

    其实,只要你看过上面那个方法,那么这个方法的作用就很明显了,该方法的作用:从运行循环的指定输入模式中删除端口。这里就不多说参数什么的了,同上所示即可。

    这里,还有几点需要注意:

    • 如果您将端口添加到多个输入模式,则必须分别从每个模式中删除它。

    结论:同上。

    参考文章

    1. iOS RunLoop了解和使用

    后记

    未完,待续~~~~

    相关文章

      网友评论

      • lenolee:注意一下翻译质量
        刀客传奇:@lenolee 哈哈,还是你组织的好:smiley:
        lenolee:@刀客传奇 不是不对,是翻译的不太好,有点费解(不过还是要感谢你的分享)
        eg:To remove a timer from all run loop modes on which it is installed, send an invalidate message to the timer
        译为:要移除所有运行循环模式下的timer的话,给它发送一个invalidate消息即可。
        是否比文中翻译的“要从其安装的所有运行环路模式中删除定时器,请向定时器发送无效invalidate消息”好呢?鄙人愚见
        刀客传奇:@lenolee 我尽力了,哪里不对麻烦指正

      本文标题:NSRunloop简单细说(三)—— 定时器和端口

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