美文网首页
认识NSRunLoop

认识NSRunLoop

作者: 19ae99975b90 | 来源:发表于2016-01-06 23:59 被阅读0次

    看过很多NSRunLoop的讲解,很枯燥,扯理论,真的不容易理解
    NSRunLoop其实就像是个监听器。。检查输入源(input source)和定时源(timer source)做回调用的。。。。

    定时源(timer source):定期或时间延迟事件(NSTimer)```
    
    每个线程都有runloop,如果有事件数据,run loop 就发送消息,通知各个对象。如果runloop没发现任何事件要处理,就把线程休眠掉,节省资源消耗,这就是runloop的用处。。节省硬件资源!
    
    主线程的runloop是默认打开的,子线程的runloop是默认关闭的,一般的线程执行完任务就结束了,所以开了runloop也没用。所以如果有需要长期检查的异步事件,才需要开启。
    
    我们写一个简单的runloop例子
    

    //创建一个子线程,在线程的执行方法中,再启动一个NSTimer
    -(void)run
    {
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(count) object:nil];
    [thread start];
    }

    -(void)count
    {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(beginCount) userInfo:nil repeats:YES];
    //启动一个NSTimer以后,因为是在子线程中启动的,所以,必须将NSTimer对象加入到当前线程的runloop中,才能正常的计时

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    [[NSRunLoop currentRunLoop] run];
    

    }

    我们可以通过调用NSRunLoop的类方法currentRunLoop来获取当前线程的runloop, addTimer是添加一个定时源,在定时源启动之前,线程是处于一个休眠状态的。除非runLoop还绑定了其他的事件源唤醒了线程,(当前例子只有一个定时源)。后面的forMode有很多模式,大体讲一下
    
    **NSDefaultRunLoopMode**:默认模式中几乎包含了所有输入源(NSConnection除外),一般情况下应使用此模式。
    
    **NSConnectionReplyMode**:处理NSConnection对象相关事件,系统内部使用,用户基本不会使用。
    
    **UITrackingRunLoopMode**:在拖动loop或其他user interface tracking loops时处于此种模式下,在此模式下会限制输入事件的处理。
    
    **NSRunLoopCommonModes**:这是一个伪模式,其为一组run loop mode的集合,将输入源加入此模式意味着在Common Modes中包含的所有模式下都可以处理。在Cocoa应用程序中,默认情况下Common Modes包含default modes,modal modes,event Tracking modes.
    
    -------------------
    >我们以前快速滑动UITableView/scrollView时会发现NSTimer停止fire。其实就是NSTimer所在的MainRunloop是defaultMode,但是如果滑动tableview时,当前的runloop会强制切换到UITrackingRunLoopMode,导致NSTimer停止fire,其他输入事件也没了响应
    
    换个思路,如果我们想让当前线程的NSTimer停止Fire, 停止接受输入事件,只需要执行下面代码
    

    [currentRunLoop runMode:UITrackingRunLoopMode beforeDate:date];

    
    我们知道,只有需要长期检查的异步事件,才需要开启runloop,那我们看下AFNetWorking里的runloop
    ![](https://img.haomeiwen.com/i1367090/0b7c5bc6410dcc5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    >AF希望能在后台线程接收 Delegate 回调,所以在AFURLConnectionOperation 这个类里创建了一个线程,并在这个线程中启动了一个 RunLoop:
    RunLoop 启动至少要有一个 Timer或Source,但是afnet扔了一个NSMachPort进来,可以通过port传入消息,使runloop不会退出
    当项目进入后台时,AFNetworking 通过调用
    ``` [NSObject performSelector:onThread:]```这个方法把任务扔到后台线程runloop中去接收回调
    
    -------------------
    ##
    AFNetworking 3.0 以后换成了URLSession  自带后台线程,就不用这么麻烦啦~

    相关文章

      网友评论

          本文标题:认识NSRunLoop

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