zoukankan      html  css  js  c++  java
  • Runloop -------iOS

    正文

    1.NSTimer 和 NSRunloop 关系

    滑动页面时 timer 会暂停的问题,为什么会暂停,怎么解决?

    因为:用scheduledTimerWithTimeInterval:注册timer时runloop会默认为NSDefaultRunLoopMode这个mode,当scrollView滚动的时候,runloop是处于UITrackingRunLoopMode的模式下的,这个模式下,是不会处理NSDefaultRunLoopMode 的消息(因为RunLoop Mode不一样),要想在scrollView滚动的同时也接受其它runloop的消息,我们需要改变两者之间的runloopmode.

    怎么解决:

        [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];

    整体栗子:

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.count = 0;
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
        [self.view addSubview:self.tableView];
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
        NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
        NSLog(@"%@",model);
        
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
        
    }
    -(void)viewDidDisappear:(BOOL)animated
    {
        [super viewDidDisappear:animated];
        [self.timer invalidate];
        self.timer = nil;
    }
    -(void)timeAction
    {
        self.count++;
        NSLog(@"%ld",self.count);
        NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
        NSLog(@"%@",model);
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        cell.textLabel.text = @"aaaa";
        return cell;
    }
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return 100;
    }
    -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
        NSLog(@"%@",model);
    }
    -(UITableView *)tableView
    {
        if(!_tableView) {
            _tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
        }
        return _tableView;
    }

     

    ----------------------更新 -- 20181022 -----------------------------------------------------------------------

     

    1.Runloop是什么?

    Runloop是线程的基础架构部分.是一个事件循环处理.是用来不停的调配工作(可以节省CPU)和处理输入事件(输入源(input source)和定时源(timer source))(后面解释).

    2.Runloop在哪?

    每一个线程,包括主线程,都对应一个Runloop,主线程的Runloop默认是运行的,自己创建的需要手动运行

    3.什么时候用Runloop

    当需要和改线程进行交互的时候,并且需要改线程监听某项事务的时候,主线程Runloop默认是开启的,如果是自己创建的线程,需要手动运行Runloop,来让线程一直不退出,Runloop就是有事件的时候执行对应的函数,没有的时候进行休眠

    4.Runloop处理的输入事件:输入源(input source)和定时源(timer source)

       4.1 输入源(input source):

                   传递异步事件,通常消息来自于其他线程或程序。输入源传递异步消息给相应的处理例程,并调用runUntilDate:方法来退出(在线程里面相关的NSRunLoop对象调用)

       4.2 定时源(timer source)

                        定时源在预设的时间点同步方式传递消息,这些消息都会发生在特定时间或者重复的时间间隔。定时源则直接传递消息给处理例程,不会立即退出run loop

    // 创建定时器源有两种方法,
    
    //方法一:
    
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:4.0
    
                                                         target:self
    
                                                       selector:@selector(backgroundThreadFire:) userInfo:nil
    
                                                        repeats:YES];
    
        [[NSRunLoop currentRunLoop] addTimer:timerforMode:NSDefaultRunLoopMode];
    
     
    
    //方法二:
    
    [NSTimer scheduledTimerWithTimeInterval:10
    
                                            target:self
    
                                           selector:@selector(backgroundThreadFire:)
    
                                           userInfo:nil
    
                                           repeats:YES];

    5.Runloop的观察者

    run loop观察者则是在run loop本身运行的特定时候触发,在创建的时候你可以指定run loop观察者可以只用一次或循环使用。若只用一次,那么在它启动后,会把它自己从run loop里面移除,而循环的观察者则不会。定义观察者并把它添加到run loop,只能使用Core Fundation

    //如何创建run loop的观察者:
    
    - (void)addObserverToCurrentRunloop
    
    {
    
        // The application uses garbage collection, so noautorelease pool is needed.
    
        NSRunLoop*myRunLoop = [NSRunLoop currentRunLoop];
    
       
    
        // Create a run loop observer and attach it to the runloop.
    
        CFRunLoopObserverContext  context = {0, self, NULL, NULL, NULL};
    
       CFRunLoopObserverRef    observer =CFRunLoopObserverCreate(kCFAllocatorDefault,
    
                                                                  kCFRunLoopBeforeTimers, YES, 0, &myRunLoopObserver, &context);
    
       
    
        if (observer)
    
        {
    
            CFRunLoopRef    cfLoop = [myRunLoop getCFRunLoop];
    
           CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode);
    
        }
    
    }
    
    //其中,kCFRunLoopBeforeTimers表示选择监听定时器触发前处理事件,后面的YES表示循环监听。

    6.RunLoop的事件队列

    每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:

    1. 通知观察者run loop已经启动
    2. 通知观察者任何即将要开始的定时器
    3. 通知观察者任何即将启动的非基于端口的源
    4. 启动任何准备好的非基于端口的源
    5. 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
    6. 通知观察者线程进入休眠
    7. 将线程置于休眠直到任一下面的事件发生:通知观察者线程将被唤醒。
      • 某一事件到达基于端口的源
      • 定时器启动
      • Run loop设置的时间已经超时
      • run loop被显式唤醒
    8. 处理未处理的事件通知观察者run loop结束。
      • 如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
      • 如果输入源启动,传递相应的消息
      • 如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
    9. 通知观察者run loop结束。

    参考:http://blog.csdn.net/ztp800201/article/details/9240913

  • 相关阅读:
    成为 Team Leader 后我最关心的那些事
    《管理的实践》读书心得
    玩黑客学校CTF
    DHCP中继器
    test
    初窥XSS跨站脚本攻击
    TCP/IP模型
    逻辑漏洞-客户端验证的邮箱-Web渗透实例之中国教育部青少年普法网站逻辑漏洞
    逻辑漏洞-支付风险-大疆某处支付逻辑漏洞可1元买无人机
    逻辑漏洞-密码找回之验证码发给了客户端
  • 原文地址:https://www.cnblogs.com/miaomiaocat/p/5084110.html
Copyright © 2011-2022 走看看