121

每当我试图下载一个大文件或其他东西时UIScrollViewMPMapView只要我触摸 iPhone 屏幕,下载过程就会停止。值得庆幸的是, Jörn的一篇很棒的博客文章提出了另一种选择,NSRunLoopCommonModes用于连接。

这让我了解了 NSDefaultRunLoopMode 和 NSRunLoopCommonModes 这两种模式的细节,但苹果文档并没有很好地解释,只是说

NSDefaultRunLoopMode

处理 NSConnection 对象以外的输入源的模式。这是最常用的运行循环模式。

NSRunLoopCommonModes

使用该值作为模式添加到运行循环的对象被所有已声明为“通用”模式组成员的运行循环模式监视;有关详细信息,请参阅 CFRunLoopAddCommonMode 的描述。

CFRunLoopAddCommonMode

源、计时器和观察者注册到一种或多种运行循环模式,并且仅在运行循环以其中一种模式运行时运行。通用模式是一组运行循环模式,您可以为其定义一组由这些模式共享的源、计时器和观察者。例如,无需将源注册到每个特定的运行循环模式,您可以将它注册一次到运行循环的通用伪模式,它将在通用模式集中的每个运行循环模式中自动注册。同样,当一个模式被添加到公共模式集合时,任何已经注册到公共伪模式的源、计时器或观察者都被添加到新添加的公共模式中。

谁能用人类语言解释这两者?

4

1 回答 1

213

运行循环是一种允许系统唤醒睡眠线程以便它们可以管理异步事件的机制。通常,当您运行一个线程(主线程除外)时,可以选择是否在运行循环中启动线程。如果线程在没有与外部事件交互且没有计时器的情况下运行某种类型或长时间运行的操作,则不需要运行循环,但如果您的线程需要响应传入事件,则应将其附加到运行循环以便当新事件到达时唤醒线程。这是NSURLConnection生成线程的情况,因为它们仅在传入事件(来自网络)时唤醒。

每个线程可以关联到多个运行循环,或者可以关联到可以设置为在不同模式下工作的特定运行循环。“运行循环模式”是操作系统用来建立一些规则的约定,用于何时传递某些事件或收集它们以便稍后传递。

通常所有的运行循环都设置为“默认模式”,它建立了管理输入事件的默认方式。例如:一旦鼠标拖动(Mac OS)或触摸(iOS)事件发生,则此运行循环的模式设置为事件跟踪;这意味着线程不会被新的网络事件唤醒,但这些事件将在用户输入事件终止并且运行循环再次设置为默认模式时传递;显然,这是操作系统架构师做出的选择,优先考虑用户事件而不是后台事件。

如果您决定通过使用更改NSURLConnection线程的运行循环模式scheduleInRunLoop:forModes:,则可以将线程分配给特殊的运行循环模式,而不是特定的默认运行循环。NSRunLoopCommonModes许多输入源都使用称为的特殊伪模式,包括事件跟踪。例如,将NSURLConnection的实例分配给普通模式意味着除了“默认模式”之外,还将其事件关联到“跟踪模式”。关联线程的一个优点/缺点NSRunLoopCommonModes是线程不会被触摸事件阻塞。

可以在普通模式中添加新模式,但这是一个相当低级的操作。

我想通过添加一些注释来结束:

  • 通常我们需要使用从网络下载的一组图像或缩略图和一个表格视图。我们可能认为在表格视图滚动时从网络下载这些图像可以改善用户体验(因为我们可以在滚动时看到图像),但这并不有利,因为滚动的流动性会受到很大影响。在这个带有NSURLConnection运行循环的例子中,不应该使用;最好使用UIScrollView委托方法来检测滚动何时终止,然后更新表格并从网络下载新项目;

  • 您可以考虑使用 GCD,它可以帮助您“保护”您的代码免受运行循环管理问题的影响。在上面的示例中,您可以考虑将网络请求添加到自定义串行队列。

于 2011-08-28T20:38:09.810 回答