ios NSDefaultRunLoopMode 与 NSRunLoopCommonModes

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7222449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:16:49  来源:igfitidea点击:

NSDefaultRunLoopMode vs NSRunLoopCommonModes

iphoneiosmultithreadingnsrunloop

提问by Stkim1

Whenever I try to download a big file behind UIScrollView, MPMapViewor something, the downloading process gets halted as soon as I touch iPhone screen. Thankfully, an awesome blog post by J?rnsuggests an alternative option, using NSRunLoopCommonModesfor connection.

每当我尝试下载一个大文件的背后UIScrollViewMPMapView或者什么的,下载过程被当我触摸iPhone屏幕停止。值得庆幸的是,J?rn 的一篇很棒的博客文章提出了另一种选择,NSRunLoopCommonModes用于连接。

That gets me look into detail of the two modes, NSDefaultRunLoopMode and NSRunLoopCommonModes, but the apple document does not kindly explain, other than saying

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

NSDefaultRunLoopMode

NSDefaultRunLoopMode

The mode to deal with input sources other than NSConnection objects. This is the most commonly used run-loop mode.

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

NSRunLoopCommonModes

NSRunLoopCommonModes

Objects added to a run loop using this value as the mode are monitored by all run loop modes that have been declared as a member of the set of “common" modes; see the description of CFRunLoopAddCommonMode for details.

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

CFRunLoopAddCommonMode

CFRunLoopAddCommonMode

Sources, timers, and observers get registered to one or more run loop modes and only run when the run loop is running in one of those modes. Common modes are a set of run loop modes for which you can define a set of sources, timers, and observers that are shared by these modes. Instead of registering a source, for example, to each specific run loop mode, you can register it once to the run loop's common pseudo-mode and it will be automatically registered in each run loop mode in the common mode set. Likewise, when a mode is added to the set of common modes, any sources, timers, or observers already registered to the common pseudo-mode are added to the newly added common mode.

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

Can anyone please explain the two in human language?

任何人都可以用人类语言解释这两者吗?

回答by viggio24

A run loop is a mechanism that allows the system to wake up sleeping threads so that they may manage asynchronous events. Normally when you run a thread (with the exception of the main thread) there is an option to start the thread in a run loop or not. If the thread runs some sort or long-running operation without interaction with external events and without timers, you do not need a run loop, but if your thread needs to respond to incoming events, it should be attached to a run loop in order to wake up the thread when new events arrive. This is the case of NSURLConnectiongenerated threads, as they only wake on incoming events (from the network).

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

Each thread can be associated to multiple run loops, or can be associated to a specific run loop that can be set to work in different modes. A "run loop mode" is a convention used by the OS to establish some rules for when to deliver certain events or collect them to be delivered later.

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

Usually all run loops are set to the "default mode" which establishes a default way to manage input events. For example: as soon as a mouse-dragging (Mac OS) or touch (on iOS) event happens then the mode for this run loop is set to event tracking; this means that the thread will not be woken up on new network events but these events will be delivered later when the user input event terminates and the run loop set to default mode again; obviously this is a choice made by the OS architects to give priority to user events instead of background events.

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

If you decide to change the run loop mode for your NSURLConnectionthread, by using scheduleInRunLoop:forModes:, then you can assign the thread to a special run loop mode, rather than the specific default run loop. The special pseudo-mode called NSRunLoopCommonModesis used by many input sources including event tracking. For example assigning NSURLConnection's instance to the common mode means associates its events to "tracking mode" in addition to the "default mode". One advantage/disadvantage of associating threads with NSRunLoopCommonModesis that the thread will not be blocked by touch events.

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

New modes can be added to the common modes, but this is quite a low-level operation.

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

I would like to close by adding a few notes:

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

  • Typically we need to use a set of images or thumbnails downloaded from the network with a table view. We may think that downloading these images from the network while the table view is scrolling could improve the user experience (since we could see the images while scrolling), but this is not advantageous since the fluidity of scrolling can suffer greatly. In this example with NSURLConnectiona run loop should not be used; it would be better to use the UIScrollViewdelegate methods to detect when scrolling is terminated and then update the table and download new items from the network;

  • You may consider using GCD which will help you to "shield" your code from run loop management issues. In the example above, you may consider adding your network requests to a custom serial queue.

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

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