美文网首页
iOS基础知识梳理 - Runloop

iOS基础知识梳理 - Runloop

作者: babyloveblues | 来源:发表于2019-08-04 17:35 被阅读0次

消息循环

消息循环在主线程上的使用

  1. 消息
    我们可以简单的把消息理解为用户的输入事件
  2. 循环

什么是RunLoop

  • runloop就是消息循环,每个线程内部都有一个消息循环。
  • 只有主线程的消息循环默认开启,子线程的消息循环默认不开启。

RunLoop目的

  • 保证程序不退出
  • 负责处理输入事件
  • 如果事件没有发生,会让程序进入休眠状态

事件类型

  • input source(输入源)&Timer source(定时源)
    输入源可以是键盘鼠标,NSPort,NSConnection等对象,定时源是NSTimer事件

如何使用

(1)创建输入源(NSTimer为例)
(2)指定该事件(源)在循环运行中的模式,并且加入循环

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
屏幕快照 2019-08-04 下午7.12.08.png

下面的代码示例可以比喻为,一个患牙病的人应该去综合性医院而不应该去妇产科医院就诊

- (void)demo{
    
    // 创建NSTimer
    NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(task) userInfo:nil repeats:YES];
    // 把定时源加入到当前线程下消息循环中
    // 参数1: 定时源
    // 参数2: NSDefaultRunLoopMode

    /**
     现象:
     NSDefaultRunLoopMode 拖动界面,定时源不运行
     NSRunLoopCommonModes 拖动界面不受影响(KCFRunloopDefaultMode,UITrackingRunloopMode都是其中的一种)
     没有拖动界面 KCFRunloopDefaultMode
     拖动界面 UITrackingRunloopMode
     */
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    
}

使用总结
(1)创建消息
(2)把消息放进循环
(3)在于循环的模式匹配的时候,消息运行

消息循环在子线程上的使用

特点:自线程默认不开启消息循环,主线程默认开启消息循环

// 子线程的消息循环
-(void)demo2{
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(task2) object:nil];
    thread.name = @"新创建的子线程";
    [thread start];
    
    // 往指定线程的消息循环中加入源
    [self performSelector:@selector(addTask) onThread:thread withObject:nil waitUntilDone:NO];
}

-(void)task{
    NSLog(@"task is running");
}

-(void)task2{
    
    NSLog(@"%@",[NSRunLoop currentRunLoop].currentMode);
    // 输出当前的线程
    NSLog(@"task2 is running %@", [NSThread currentThread]);
    
    // 开启消息循环 使用run方法无法停止消息循环
    // 方法一
    // [[NSRunLoop currentRunLoop] run];
    // 方法二 改方法受机器性能的影响很大,很老的机器并不一定可以两秒钟内停止这个runloop
    // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
    // 方法三 apple推荐的方式
    //    BOOL shouldKeepRunning = YES; //全局的
    NSRunLoop *theRL = [NSRunLoop currentRunLoop];
    while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) {
        
    }
    
    NSLog(@"runloop over!!!");
    
}

-(void)addTask{
    
    NSLog(@"addTask is running");
    
}

相关文章

网友评论

      本文标题:iOS基础知识梳理 - Runloop

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