iphone——使用run loop对象

本文详细解析了iOS应用中RunLoop的工作原理及其在不同情境下的使用方法,包括RunLoop的启动、运行、退出机制,如何通过添加inputsource或timer确保RunLoop持续运行,以及RunLoop观察者的工作流程和回调函数的作用。同时,介绍了如何通过超时时间配置和特定模式来限制RunLoop的运行,以及如何在代码中实现这些功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/lingedeng/article/details/6870692


如果你在非main thread中运行run loop,你必须至少为该run loop添加一个input sources或timer。如果你运行的run loop没有监控任何的输入源,该run loop将在你运行后立即退出。

Run loop observer

使用detachNewThreadSelector:toTarget:withObject:创建一个thread:

  1. [NSThreaddetachNewThreadSelector:@selector(observerRunLoop)toTarget:selfwithObject:nil];

在新thread的run loop中添加observer:

  1. -(void)observerRunLoop{
  2. //建立自动释放池
  3. NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
  4. //获得当前thread的Runloop
  5. NSRunLoop*myRunLoop=[NSRunLoopcurrentRunLoop];
  6. //设置Runloopobserver的运行环境
  7. CFRunLoopObserverContextcontext={0,self,NULL,NULL,NULL};
  8. //创建Runloopobserver对象
  9. //第一个参数用于分配observer对象的内存
  10. //第二个参数用以设置observer所要关注的事件,详见回调函数myRunLoopObserver中注释
  11. //第三个参数用于标识该observer是在第一次进入runloop时执行还是每次进入runloop处理时均执行
  12. //第四个参数用于设置该observer的优先级
  13. //第五个参数用于设置该observer的回调函数
  14. //第六个参数用于设置该observer的运行环境
  15. CFRunLoopObserverRefobserver=CFRunLoopObserverCreate(kCFAllocatorDefault,kCFRunLoopAllActivities,YES,0,&myRunLoopObserver,&context);
  16. if(observer){
  17. //将Cocoa的NSRunLoop类型转换成CoreFoundation的CFRunLoopRef类型
  18. CFRunLoopRefcfRunLoop=[myRunLoopgetCFRunLoop];
  19. //将新建的observer加入到当前thread的runloop
  20. CFRunLoopAddObserver(cfRunLoop,observer,kCFRunLoopDefaultMode);
  21. }
  22. //CreatesandreturnsanewNSTimerobjectandschedulesitonthecurrentrunloopinthedefaultmode
  23. [NSTimerscheduledTimerWithTimeInterval:0.1target:selfselector:@selector(doFireTimer:)userInfo:nilrepeats:YES];
  24. NSIntegerloopCount=10;
  25. do{
  26. //启动当前thread的loop直到所指定的时间到达,在loop运行时,runloop会处理所有来自与该runloop联系的inputsource的数据
  27. //对于本例与当前runloop联系的inputsource只有一个Timer类型的source。
  28. //该Timer每隔0.1秒发送触发事件给runloop,runloop检测到该事件时会调用相应的处理方法。
  29. //由于在runloop添加了observer且设置observer对所有的runloop行为都感兴趣。
  30. //当调用runUnitDate方法时,observer检测到runloop启动并进入循环,observer会调用其回调函数,第二个参数所传递的行为是kCFRunLoopEntry。
  31. //observer检测到runloop的其它行为并调用回调函数的操作与上面的描述相类似。
  32. [myRunLooprunUntilDate:[NSDatedateWithTimeIntervalSinceNow:1.0]];
  33. //当runloop的运行时间到达时,会退出当前的runloop。observer同样会检测到runloop的退出行为并调用其回调函数,第二个参数所传递的行为是kCFRunLoopExit。
  34. loopCount--;
  35. }while(loopCount);
  36. //释放自动释放池
  37. [poolrelease];
  38. }

设置observer的回调函数:

  1. voidmyRunLoopObserver(CFRunLoopObserverRefobserver,CFRunLoopActivityactivity,void*info){
  2. switch(activity){
  3. //Theentranceoftherunloop,beforeenteringtheeventprocessingloop.
  4. //ThisactivityoccursonceforeachcalltoCFRunLoopRunandCFRunLoopRunInMode
  5. casekCFRunLoopEntry:
  6. NSLog(@"runloopentry");
  7. break;
  8. //Insidetheeventprocessingloopbeforeanytimersareprocessed
  9. casekCFRunLoopBeforeTimers:
  10. NSLog(@"runloopbeforetimers");
  11. break;
  12. //Insidetheeventprocessingloopbeforeanysourcesareprocessed
  13. casekCFRunLoopBeforeSources:
  14. NSLog(@"runloopbeforesources");
  15. break;
  16. //Insidetheeventprocessingloopbeforetherunloopsleeps,waitingforasourceortimertofire.
  17. //ThisactivitydoesnotoccurifCFRunLoopRunInModeiscalledwithatimeoutof0seconds.
  18. //Italsodoesnotoccurinaparticulariterationoftheeventprocessingloopifaversion0sourcefires
  19. casekCFRunLoopBeforeWaiting:
  20. NSLog(@"runloopbeforewaiting");
  21. break;
  22. //Insidetheeventprocessingloopaftertherunloopwakesup,butbeforeprocessingtheeventthatwokeitup.
  23. //Thisactivityoccursonlyiftherunloopdidinfactgotosleepduringthecurrentloop
  24. casekCFRunLoopAfterWaiting:
  25. NSLog(@"runloopafterwaiting");
  26. break;
  27. //Theexitoftherunloop,afterexitingtheeventprocessingloop.
  28. //ThisactivityoccursonceforeachcalltoCFRunLoopRunandCFRunLoopRunInMode
  29. casekCFRunLoopExit:
  30. NSLog(@"runloopexit");
  31. break;
  32. /*
  33. Acombinationofalltheprecedingstages
  34. casekCFRunLoopAllActivities:
  35. break;
  36. */
  37. default:
  38. break;
  39. }
  40. }

启动run loop

启动run loop的方法:无条件启动,设置时间限制启动,在特殊的模式下启动。

以无条件模式进入run loop是最简单的选择,但并不是最好的选择。以无条件的形式运行run loop将使thread进入一个永久的循环,这样的操作会使用户很难对run loop进行控制。你可以为该run loop添加input source或timer,但能退出该run loop的方法就是kill。这种启动情况下并不能让run loop运行于自定义模式中。

不同于无条件方式运行run loop,使用时间限制的方式启动run loop更好。当你使用超时时间来对run loop的运行加以限制,则run loop一直运行直至事件到达或达到超时时间。如果是事件到达,run loop将事件分发给handler(处理器)进行处理并在处理完成后退出。你的代码然后重启run loop来处理下一个事件。如果是因到达超时时间而退出,you can simply restart the run loop or use the time to do any needed housekeeping。

除了超时时间,你还可以运行run loop在特定的模式下。模式和超时时间并不互斥,你可以在启动一个run loop时同时指定超时时间和模式。模式限制了投递事件给run loop的sources的类型,详细的见“iphone——NSRunLoop概念”。

退出run loop

退出run loop的方法:以超时时间配置run loop启动,显式的停止run loop(调用CFRunLoopStop函数)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值