Input Sources
输入源
Input sources deliver events asynchronously to your threads. The source of the event depends on the type of the input source, which is generally one of two categories. Port-based input sources monitor your application’s Mach ports. Custom input sources monitor custom sources of events. As far as your run loop is concerned, it should not matter whether an input source is port-based or custom. The system typically implements input sources of both types that you can use as is. The only difference between the two sources is how they are signaled. Port-based sources are signaled automatically by the kernel, and custom sources must be signaled manually from another thread.
输入源会异步的传递事件给你的线程。事件的来源取决于输入源,这通常是两个类别之一。基于端口的输入源监听你程序的硬件端口。自定义输入源监听自定义事件源。就runloop而言,输入源是基于端口还是自定义并不重要。系统通常输入源的各种类型,你可以使用。仅有的不同是如何发出信号。基于端口是由内核发出信号。自定义输入源必须由另外一个线程发出信号。
When you create an input source, you assign it to one or more modes of your run loop. Modes affect which input sources are monitored at any given moment. Most of the time, you run the run loop in the default mode, but you can specify custom modes too. If an input source is not in the currently monitored mode, any events it generates are held until the run loop runs in the correct mode.
当你创建一个输入源的时候,你将给source分配你runloop里边的一种或多种mode。mode会影响在给定时刻哪种source会被监听。大多数情况下,你在默认模式下运行你的runloop。但是你也可以专门定义你的mode。如果一个输入源不在当前监听的mode,那么这个source生成的任何事件将保持,直到runloop以正确的mode运行。
注释:简单来说就是,runloop会以不同的mode运行。在不同的mode下,source会发送不同的消息给程序进行处理。如果不在runloop不在对应的mode下运行,就不发消息。例如滑动时,程序是在runloop跟踪模式下运行,那么默认mode对应的source就不会发消息给程序执行。
The following sections describe some of the input sources.
下边几个部分描述几种输入源。
Port-Based Sources
基于端口的源
Cocoa and Core Foundation provide built-in support for creating port-based input sources using port-related objects and functions. For example, in Cocoa, you never have to create an input source directly at all. You simply create a port object and use the methods ofNSPortto add that port to the run loop. The port object handles the creation and configuration of the needed input source for you.
cocoa和cocoa基础架构cocoa用端口对象和函数为创建端口输入源提供支持。例如,在cocoa中,你从来不需要直接创建创建输入源。你只需要单单创建一个端口对象,添加它到runloop中即可。端口对象帮你创建和配置所需的输入源。
In Core Foundation, you must manually create both the port and its run loop source. In both cases, you use the functions associated with the port opaque type (CFMachPortRef,CFMessagePortRef, orCFSocketRef) to create the appropriate objects.
在核心框架中,你必须手动创建端口和它的runloop源。在这两种情况下,你使用和端口类型相关的函数来创建合适的对象。
Custom Input Sources
自定义输入源
To create a custom input source, you must use the functions associated with the CFRunLoopSourceRef opaque type in Core Foundation. You configure a custom input source using several callback functions. Core Foundation calls these functions at different points to configure the source, handle any incoming events, and tear down the source when it is removed from the run loop.
在核心框架下,为了创建一个自定义输入源,你必须结合与CFRunLoopSourceRef相关的函数。你要用几个回调函数来配置输入源。核心基础框架会在不同的点调用这些函数来配置这些源,处理任何将要发生的事件。并在runloop删除源时将其卸载。
In addition to defining the behavior of the custom source when an event arrives, you must also define the event delivery mechanism. This part of the source runs on a separate thread and is responsible for providing the input source with its data and for signaling it when that data is ready for processing. The event delivery mechanism is up to you but need not be overly complex.
当事件到达的时候除了要定义自定义源的行为,你还必须定义事件传递机制。source的这部分运行在单独的线程上,源负责向输入源提供数据,并在数据处理好的时候发送给它。事件传递机制取决于你,没必要过于复杂。
Cocoa Perform Selector Sources
cocoa执行selector源
In addition to port-based sources, Cocoa defines a custom input source that allows you to perform a selector on any thread. Like a port-based source, perform selector requests are serialized on the target thread, alleviating many of the synchronization problems that might occur with multiple methods being run on one thread. Unlike a port-based source, a perform selector source removes itself from the run loop after it performs its selector.
除了基于端口的源,cocoa还定义了一个自定义输入源,来允许你在任何线程上执行方法。像基于端口的源一样,执行选择器请求在目标线程上被序列化,减轻了多个方法在一个线程上运行可能发生的许多同步问题。与基于端口的源不同,执行选择器源会在执行完后把它从runloop中移除。
When performing a selector on another thread, the target thread must have an active run loop. For threads you create, this means waiting until your code explicitly starts the run loop. Because the main thread starts its own run loop, however, you can begin issuing calls on that thread as soon as the application calls the applicationDidFinishLaunching:method of the application delegate. The run loop processes all queued perform selector calls each time through the loop, rather than processing one during each loop iteration.
当在另一个线程上执行selector的时候,目标线程必须有一个活跃的runloop。对于你创建的线程,这意味着它会等到你的代码中显示的开始runloop。由于主线程启动自己的runloop。然而,一旦程序调用了didfinish方法,就可以在线程上发生调用。runloop在循环中每次执行所有的选择器,不是每次循环执行一个。
Table 3-2 lists the methods defined onNSObject that can be used to perform selectors on other threads. Because these methods are declared onNSObject, you can use them from any threads where you have access to Objective-C objects, including POSIX threads. These methods do not actually create a new thread to perform the selector.
下表列出了NSObject上定义了在其他线程上可以用来执行的方法。由于这些方法定义在NSObject上,你可以应用他们在任何线程上,只要你可以访问到oc对象,包括POSIX。线程。这些方法实际上并没有创建一个新的线程。
Timer Sources
定时器源
Timer sources deliver events synchronously to your threads at a preset time in the future. Timers are a way for a thread to notify itself to do something. For example, a search field could use a timer to initiate an automatic search once a certain amount of time has passed between successive key strokes from the user. The use of this delay time gives the user a chance to type as much of the desired search string as possible before beginning the search.
定时器源会在预设的将来同步发送时间到你的线程。对于线程来说,定时器是一种通知自己做事的一种方式。例如,用户输入一段时间,你就可以自动搜索进行搜索。延迟时间的应用可以给用户在开始搜索之前,有机会得到尽可能想要搜索的字符串。
Although it generates time-based notifications, a timer is not a real-time mechanism. Like input sources, timers are associated with specific modes of your run loop. If a timer is not in the mode currently being monitored by the run loop, it does not fire until you run the run loop in one of the timer’s supported modes. Similarly, if a timer fires when the run loop is in the middle of executing a handler routine, the timer waits until the next time through the run loop to its handler routine. If the run loop is not running at all, the timer never fires.
尽管定时源会生成基于定时器的通知,但是定时器不是一种实时的机制。与输入源一样,定时器也和runloop的模式相结合。如果一个定时器不属于当前循环监听的模式,直到这个runloop运行定时器支持的模式才会启动。相似的,如果当前的runloop正在处理其他事情,定时器触发,那么定时器会等到runloop下一次处理程序时。如果runloop没有启动,那么定时器从来都不会开启。
You can configure timers to generate events only once or repeatedly. A repeating timer reschedules itself automatically based on the scheduled firing time, not the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so much that it misses one or more of the scheduled firing times, the timer is fired only once for the missed time period. After firing for the missed period, the timer is rescheduled for the next scheduled firing time.
你可以配置定时器一次或者多次执行。重复执行会自动安排执行按照设定的时间重新调度,不是实际开启时间。例如,如果一个定时器运行在特定时间和之后每隔5秒。那么后边尽管后边实际开启时间延误了,但是预定时间依然是在原始的基础上隔5秒。如果延误太多,那么定时器会错过一次或多次,仅仅运行错过时期的一次。之后,将重新安排下一次的时间。