宽容他人,放过自己。

runloop

Posted on By anchoriteFili

Runloop测试.zip
iOS RunLoop 初识

Run loop就像它的名字一样,是你thread中的一个循环并对收到的事件进行处理。你的代码提供控制语句用来对run loop进行执行——换句话说:你的代码提供while或for循环来驱动run loop。在你的循环中,你使用runloop对象来“运行”事件处理代码。事件处理代码主要进行接收事件并调用事件处理函数。Run loop从两个不同的事件源中接收消息。Input sources(CFRunLoopSource)投递异步消息,通常来自于另一个thread或另一个应用程序。Timer sources(CFRunLoopTimer)当在计划的时间 或重复的时间间隔内投递同步消息。两种事件源都使用应用程序指定的处理方式对到达的事件进行处理。下图展示了run loop和不同的事件源结构。

如果我们要写多线程的程序,可能需要自己来管理RunLoop

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

RunMode:NSDefaultRunLoopMode,可以把这个理解为一个“过滤器”,我们可以只对自己关心的事件进行监视。一般NSDefaultRunLoopMode是最常用的。

启动run loop的方法:Runs the loop once,blocking for input in the specified mode until a given date.启动run loop一次,在特定的run loop mode下等待输入。 如果没有附加input source或是timer,或是过limitDate,run loop就会推出,并且方法返回NO。

Run Loop的是使用场合

  • 1.使用port或是自定义的input source来和其它线程进行通信
  • 2.在线程(非主线程)中使用timer
  • 3.使用performSelector…系列(如performSelectorOnThread,…)
  • 4.使用线程执行周期性工作

run loop不需要创建,在线程只需要调用[NSRunLoop currentRunLoop]就可以得到

代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    NSLog(@"start new thread...");
    [NSThread detachNewThreadSelector:@selector(runOnNewThread) toTarget:self withObject:nil];
    
    while (!end) {
        NSLog(@"runLoop...");
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        
        NSLog(@"runLoop end");
    }
    
    NSLog(@"ok");
}

- (void)runOnNewThread {
    NSLog(@"run for new thread...");
    sleep(1);
    [self performSelectorOnMainThread:@selector(setEnd) withObject:nil waitUntilDone:NO];
    NSLog(@"end");
}

- (void)setEnd {
    end = YES;
}

造成while循环后语句延缓执行的原因是,runloop未被唤醒。因为,改变量的值,runLoop对象根本不知道。延缓的时长总是补丁的,这是因为,哟其他事件在某个时点唤醒了主线程,这才结束了while循环。那么,向主线程发送消息,将唤醒runLoop,因此问题就解决了。