runloop使用
2014-12-09 10:47
197 查看
#import "ViewController.h" @interface ViewController () @property(nonatomic, assign) BOOL stopFlag; @end @implementation ViewController //Run loop就是一个事件处理的循环,用来不停的调动工作以及处理输入事件。使用Run loop的目的就是节省CPU效率,线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。 //何时使用Run loop:对于辅助线程,在需要和线程有更多的交互时,才使用Run loop。比如使用端口或者自定义输入源和其它线程通讯、使用线程定时器、Cocoa中使用performSelector 的方法(Performing selectors on other threads)、使线程周期性工作。 //Run loop有两种来源:输入源和定时源。输入源传递异步事件,通常消息来自于其他线程或程序。输入源的种类:基于端口的输入源和自定义输入源。定时源则传递同步事件,发生在特定时间或者重复的时间间隔。 - (void)viewDidLoad { [super viewDidLoad]; // // Do any additional setup after loading the view, typically from a nib. // //使用Run loop对象提供了添加输入源、定时器和Run loop的观察者以及启动Runloop的接口,使用Run loop包括获取--配置--启动--退出四个过程。 // //1、获取Run loop的对象 // //A、通过NSRunLoop获取 // //获得当前thread的Run loop // NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop]; // //将Cocoa的NSRunLoop类型转换成core Foundation的CFRunLoopRef类型 // CFRunLoopRef c = [myRunLoop getCFRunLoop]; // //开辟新线程 // [NSThread detachNewThreadSelector:@selector(newThreadProcess) toTarget:self withObject:nil]; _stopFlag = NO; NSLog(@"Start a new thread."); [NSThread detachNewThreadSelector: @selector(newThreadProc) toTarget: self withObject: nil]; while (!_stopFlag) { NSLog(@"Beginrunloop"); [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]; NSLog(@"Endrunloop."); } NSLog(@"OK"); } - (void)newThreadProcess{ @autoreleasepool { //获得thread的RunLoop NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop]; //设置Run loop observer的运行环境 CFRunLoopObserverContext context = {0,(__bridge void *)(self),NULL,NULL,NULL}; //创建Run loop observer对象 //第一个参数用于分配observer对象的内存 //第二个参数用以设置observer所要关注的事件,详见回调函数myRunLoopObserver中注释 //第三个参数用于标识该observer是在第一次进入runloop时执行还是每次进入run loop处理时均执行 //第四个参数用于设置该observer的优先级 //第五个参数用于设置该observer的回调函数 //第六个参数用于设置该observer的运行环境 CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &myRunLoopObserver, &context); if(observer) { //将Cocoa的NSRunLoop类型转换成CoreFoundation的CFRunLoopRef类型 CFRunLoopRef cfRunLoop = [myRunLoop getCFRunLoop]; //将新建的observer加入到当前thread的runloop CFRunLoopAddObserver(cfRunLoop, observer, kCFRunLoopDefaultMode); } //定时器每隔一秒执行一次方法 [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector:@selector(timerProcess) userInfo: nil repeats: YES]; NSInteger loopCount = 2; do{ //启动当前thread的loop直到所指定的时间到达,在loop运行时,runloop会处理所有来自与该run loop联系的inputsource的数据 //对于本例与当前run loop联系的inputsource只有一个Timer类型的source。 //该Timer每隔1秒发送触发事件给runloop,run loop检测到该事件时会调用相应的处理方法。 //由于在run loop添加了observer且设置observer对所有的runloop行为都感兴趣。 //当调用runUnitDate方法时,observer检测到runloop启动并进入循环,observer会调用其回调数,第二个参数所传递的行为是kCFRunLoopEntry。 //observer检测到runloop的其它行为并调用回调函数的操作与上面的描述相类似。 [myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]]; //当run loop的运行时间到达时,会退出当前的runloop。observer同样会检测到runloop的退出行为并调用其回调函数,第二个参数所传递的行为是kCFRunLoopExit。 loopCount--; }while (loopCount); } } void myRunLoopObserver(CFRunLoopObserverRef observer,CFRunLoopActivity activity, void *info){ switch (activity) { case kCFRunLoopEntry: NSLog(@"run loop entry"); break; case kCFRunLoopBeforeTimers: NSLog(@"run loop before timers"); break; case kCFRunLoopBeforeSources: NSLog(@"run loop before sources"); break; case kCFRunLoopBeforeWaiting: NSLog(@"run loop before waiting"); break; case kCFRunLoopAfterWaiting: NSLog(@"run loop after waiting"); break; case kCFRunLoopExit: NSLog(@"run loop exit"); break; default: break; } } - (void)timerProcess{ for (int i=0; i<5; i++) { NSLog(@"In timerProcess count = %d.", i); sleep(1); } } //---------------------------- //while循环后执行的语句会在很长时间后才被执行。因为,改变变量StopFlag的值,runloop对象根本不知道,runloop在这个时候未被唤醒。有其他事件在某个时点唤醒了主线程,这才结束了while循环,但延缓的时长总是不定的。 //缩短runloop的休眠事件是不合适的,因为这样会导致runloop被经常唤醒,违背了runloop的设计初衷。runloop就是为了提供效率,有工作时忙于工作,没工作时处于休眠状态。 //可以改为向主线程发送消息,唤醒runloop。 -(void)newThreadProc{ NSLog(@"Enter newThreadProc."); for (int i=0; i<10; i++) { NSLog(@"InnewThreadProc count = %d.", i); sleep(1); } // _stopFlag = YES; [self performSelectorOnMainThread: @selector(setEnd) withObject: nil waitUntilDone: NO]; NSLog(@"Exit newThreadProc."); } -(void)setEnd{ _stopFlag = YES; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
相关文章推荐
- 什么时候使用runloop?
- 使用runloop阻塞线程的正确写法
- 在子线程中使用runloop,正确操作NSTimer计时的注意点 三种可选方法
- Runloop的使用
- Runloop的最简单使用
- 使用runloop阻塞线程
- RunLoop的一些简单使用
- Runloop的使用
- runloop的使用
- 使用runloop阻塞线程的正确写法
- 使用runloop阻塞线程的正确写法
- 在子线程中使用runloop,正确操作NSTimer计时的注意点 三种可选方法
- runloop的基本使用
- 单独线程上使用RunLoop开启NSTimer
- ios下使用runloop阻塞线程
- 使用runloop阻塞线程的正确写法
- runloop实现原理初解 和 使用runloop阻塞线程
- Runloop的基本使用
- RunLoop源码分析、基本使用场景和常见问题
- iOS 如何使用 NSTimer 以及 runloop 和 NSTimer 的关系