在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); }
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);
因为定时器每隔0.1秒发送一个消息,这样每次runUntilDate应该会接受到2次消息。(把0.2改成0.21啥的,应该就是2次,0.2的话还不一定,因为当发送第二次定时器的时候,run loop生命周期也刚刚到,可能第二次不一定能被处理)。
大致的流程就是
1. 定时器发送消息,每隔0.1秒
2. run loop收到消息,调用doFireTimer函数。
运行如下:可以从左边的调用栈里面看到doFireTimer是从run loop里面调用的。
完整代码如下:只要在主线程里面启动这个线程就可以了。
[NSThread detachNewThreadSelector:@selector(MyThread) toTarget:self withObject: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); }