首页 > 代码库 > ios - run loop (timer)

ios - run loop (timer)

在ios开发多线程程序的时候,往往会碰到run loop。

对于run loop, 苹果开发网站上有非常详细的说明,https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

强烈建议啃下来,不要怕英文。

copy了一下图片:

技术分享

这里就写个Timer sources的简单例子。

系统创建一个线程的时候,就已经默认创建了一个run loop了,除了主线程默认run loop就是运行的,其他的辅助线程虽说已经创建了run loop但是并没有运行。


获取线程的run loop对象

    NSRunLoop* loop = [NSRunLoop currentRunLoop];
通过上面简单的代码就可以获取当前线程的run loop对象。


创建一个定时器

    // Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doFireTimer:) userInfo:nil repeats:YES];
doFireTimer每0.1秒会被调用一次。简单如下:

- (void) doFireTimer:(NSTimer *)timer
{
    NSLog(@"doFireTimer, %f", timer.timeInterval);
}

启动run loop

    NSInteger loopCount = 2;
    do
    {
        // 启动当前thread的run loop直到所指定的时间到达,在run loop运行时,run loop会处理所有来自与该run loop联系的input sources的数据
        // 对于本例与当前run loop联系的input source只有Timer类型的source
        // 该Timer每隔0.1秒发送触发时间给run loop,run loop检测到该事件时会调用相应的处理方法(doFireTimer:)
        // 由于在run loop添加了observer,且设置observer对所有的run loop行为感兴趣
        // 当调用runUntilDate方法时,observer检测到run loop启动并进入循环,observer会调用其回调函数,第二个参数所传递的行为时kCFRunLoopEntry
        // observer检测到run loop的其他行为并调用回调函数的操作与上面的描述相类似
        [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.2]];
        // 当run loop的运行时间到达时,会退出当前的run loop,observer同样会检测到run loop的退出行为,并调用其回调函数,第二个参数传递的行为是kCFRunLoopExit.
        --loopCount;
    }while(loopCount);

调用runUntilDate函数,这个函数会使当前的run loop运行0.2秒。这里总共调用2次。

因为定时器每隔0.1秒发送一个消息,这样每次runUntilDate应该会接受到2次消息。(把0.2改成0.21啥的,应该就是2次,0.2的话还不一定,因为当发送第二次定时器的时候,run loop生命周期也刚刚到,可能第二次不一定能被处理)。

大致的流程就是

1. 定时器发送消息,每隔0.1秒

2. run loop收到消息,调用doFireTimer函数。

运行如下:可以从左边的调用栈里面看到doFireTimer是从run loop里面调用的。

技术分享


完整代码如下:只要在主线程里面启动这个线程就可以了。

[NSThreaddetachNewThreadSelector:@selector(MyThread)toTarget:selfwithObject:nil];

- (void) doFireTimer:(NSTimer *)timer
{
    NSLog(@"doFireTimer, %f", timer.timeInterval);
}



- (void) MyThread
{
    NSRunLoop* loop = [NSRunLoop currentRunLoop];
    
    // Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doFireTimer:) userInfo:nil repeats:YES];

    NSInteger loopCount = 2;
    do
    {
        // 启动当前thread的run loop直到所指定的时间到达,在run loop运行时,run loop会处理所有来自与该run loop联系的input sources的数据
        // 对于本例与当前run loop联系的input source只有Timer类型的source
        // 该Timer每隔0.1秒发送触发时间给run loop,run loop检测到该事件时会调用相应的处理方法(doFireTimer:)
        // 由于在run loop添加了observer,且设置observer对所有的run loop行为感兴趣
        // 当调用runUntilDate方法时,observer检测到run loop启动并进入循环,observer会调用其回调函数,第二个参数所传递的行为时kCFRunLoopEntry
        // observer检测到run loop的其他行为并调用回调函数的操作与上面的描述相类似
        [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.2]];
        // 当run loop的运行时间到达时,会退出当前的run loop,observer同样会检测到run loop的退出行为,并调用其回调函数,第二个参数传递的行为是kCFRunLoopExit.
        --loopCount;
    }while(loopCount);
}



ios - run loop (timer)