美文网首页
iOS中Run Loop的那些坑

iOS中Run Loop的那些坑

作者: KYPoseidonL | 来源:发表于2016-04-01 09:32 被阅读527次

回顾一下,Run Loop就是个监听事件的循环,会不停的检查它的事件源(Timer和Input Source)有没有事件发生,如果有事件发生就处理事件或者调用事件的处理方法。

坑一

在线程中添加Timer时,肯定需要先生成Timer对象啦,有类方法也有实例方法,如果是使用scheduledTimerWith***接口生成的Timer对象,会自动添加到当前线程的NSDefaultRunLoopMode中;如果是其他接口生成的Timer对象,则需要用-addTimer:forMode
添加Timer,这样做的好处是可以指定添加Timer的Run Loop以及模式。

坑二

如果Run Loop中添加的是Timer而没有其他Input Source,而这个Timer只运行一次,那么Timer事件触发后Timer事件源就会从Run Loop删除,那么再运行Run Loop就会立刻返回;同时Timer事件触发是不会让Run Loop返回的,即使使用CF层的CFRunLoopRef运行接口SInt32 CFRunLoopRunInMode (mode, seconds, returnAfterSourceHandled);
运行Run Loop,其第三个参数为YES,Timer事件触发仍然不会导致当前Run Loop的运行返回。

坑三

如果是使用NSRunLoop,有三个运行的接口:
//运行 NSRunLoop,运行模式为默认的NSDefaultRunLoopMode模式,没有超时限制- (void)run;//运行 NSRunLoop: 参数为运行模式、时间期限,返回值为YES表示是处理事件后返回的,NO表示是超时或者停止运行导致返回的。[Update]: 感谢网友olo的提醒:返回值只有在RunLoop没有运行的情况下才返回NO。比如:1)没有添加输入源和定时器源 2)mode为NSRunLoopCommonModes 或UITrackingRunLoopMode 等“非法”参数。如果超时的话返回YES,即使limitDate的初始值小于当前的Date,RunLoop也会执行一次然后马上返回YES。- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;//运行 NSRunLoop: 参数为运时间期限,运行模式为默认的NSDefaultRunLoopMode模式- (void)runUntilDate:(NSDate *)limitDate;

建议是使用第二个接口来运行,因为它能够设置Run Loop的运行参数最多,而且最重要的是可以使用CFRunLoopStop(runLoopRef)来停止Run Loop的运行,而第一个和第三个接口无法使用CFRunLoopStop(runLoopRef)来停止Run Loop的运行。

坑四

在使用NSURLConnection或者NSStream时,需要考虑到Run Loop的问题,默认情况下这两个对象生成后都是运行在当前线程的NSDefaultRunLoopMode模式的,如果是在主线程,那么在滚动ScrollView或者TableView时,主线程的Run Loop会运行在UITrackingRunLoopMode模式,那么NSURLConnection或者NSStream的回调就无法运行。因此最好是指定NSURLConnection或NSStream在Run Loop中的运行模式,两者有相同的接口- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
来设置NSURLConnection和NSStream的Run Loop以及模式,而且设置的Mode要设置为NSRunLoopCommonModes,因为NSRunLoopCommonModes默认会包含NSDefaultRunLoopMode和UITrackingRunLoopMode,这样无论Run Loop运行在哪个模式,都可以保证NSURLConnection或者NSStream的回调可以被调用。另外如果是在子线程中你设置了自定义的Run Loop模式,还可以用接口CFRunLoopAddCommonMode(runLoopRef, mode)
添加到NSRunLoopCommonModes。

不过NSURLConnection的使用有点特殊,必须使用它的designated initializer - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately
生成NSURLConnection对象,而且第三个参数是否立刻启动NSURLConnection要设置为NO,之后再用- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
设置Run Loop与模式,再调用[NSURLConnectionObject start]
启动。如果是其他接口生成NSURLConnection,用- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
设置Run Loop和mode都不会起作用。

相关文章

  • iOS中Run Loop的那些坑

    回顾一下,Run Loop就是个监听事件的循环,会不停的检查它的事件源(Timer和Input Source)有没...

  • 详解Run Loop

    Run Loop Run Loop是事件驱动的。 iOS中有2套API来访问使用Run LoopFoundatio...

  • 如何手动唤醒RunLoop

    在iOS 中,除了source1可以自己唤醒run loop之外,其他的事件都需要用户手动唤醒run loop才可...

  • 备战2020——iOS面试题汇总!(栏目将持续更新)

    runloop 推荐相关文章 iOS 对于Run Loop的理解? 2019 iOS面试题-----RunLoop...

  • runloop

    走进Run Loop的世界 (一):什么是Run Loop?走进Run Loop的世界 (二):如何配置Run L...

  • runloop阻塞线程的正确写法 & 子线程常驻后台

    转载自: iOS RunLoop 初识深入理解RunLoopiOS多线程编程指南(三)Run Loop 1.Run...

  • iOS Runloop学习笔记

    一、** what is run loop ** 1、A run loop is an abstraction t...

  • iOS run loop 详解

    一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我...

  • iOS之Run Loop

    Run Loop是用于管理在线程上异步执行事件的基础方式。Run Loop用来监听线程的一个或多个事件源。当事件发...

  • iOS - run loop详解

    从事iOS编程1年,一直没搞懂RunLoop原理,不知道大家有没有想过这个问题,一个应用开始运行以后放在那...

网友评论

      本文标题:iOS中Run Loop的那些坑

      本文链接:https://www.haomeiwen.com/subject/xdcylttx.html