第一次学习:
文档地址:
重要参考文章:
https://blog.ibireme.com/2015/05/18/runloop/
学习笔记:
1、The NSRunloop class declares the programmatic interface to objects that manage input sources.
NSRunloop声明一些面向管理输入源的对象的编程接口
2、An NSRunloop object processes input for sources such as mouse and keyboard events from the window system,NSPort objects, and NSConnection objects.
一个NSRunloop对象为这些资源处理输入源,这些资源包括正如来自窗口系统的鼠标和键盘,NSPort对象,NSConnection对象等。
3、An NSRunloop object also processes NSTimer events.
一个NSRunloop 对象也处理timer事件。
4、Your application cannot either create or explicitly manage NSRunLoop objects.
你的应用既不能创建NSRunLoop对象也不能管理NSRunLoop对象。
5、Each NSThread object —including the application’s main thread —has an NSRunloop object automatically created for it as needed.
每一个NSThread object 包括主线程,都有一个runloop,这个runloop在需要的时候会被自动创建。
6、If you need to access the current thread’s run loop ,you do so with the class method currentRunloop
如果你需要处理主线程的run loop,你可以用类方法currentRunloop
7、Note that from the perspective of NSRunLoop ,NSTimer objects are not “input” —they are a special type , and of the things that means is that they do not cause the run loop to return when they fire.
注意从NSRunLoop视角来看,NSTimer 对象不是输入源,他们是一种特殊的类型,特殊之处之一在于当他们(timer)启动的时候,他们不会引起运行循环返回。
8、The NSRunLoop class is generally not considered to be thread-safe and its methods should only be called within the context of the current thread.You should never try to call the methods of an NSRunLoop object running in a different thread, as doing so might cause unexpected results.
NSRunLoop class 通常认为不是线程安全的,并且它的方法只能在目前线程的上下文被调用,你应该从不调用跑在不同线程的runloop方法,这么做的话可能会引发意外的结果。
9、addTimer : forMode:
用一个被给的输入源模型注册一个timer
10、Run loops are part of the fundamental infrastructure associated with threads.
运行循环是联系线程最基本的框架之一
11、A run loop is an event processing loop that you use to schedule work and coordinate the receipt of incoming events.
一个运行循环是一个处理循环的事件,使用这个事件你能处理工作和调整进来的事件
12、The purpose of a run loop is to keep your thread busy when there is work to do and put your thread to sleep when there is none.
一个运行循环的目的是当有工作做的时候保持你的线程忙碌,没有的时候让你线程休息。
13、Run loop management is not entirely automatic.You must still design your thread’s code to start the run loop at appropriate times and respond to incoming events.
运行循环不是全自动的,你必须设计你的线程的码在合适的时候开启运行循环,并且反馈传入的事件。
14、Both Cocoa and Core Foundation provide run loop objects to help you configure and manage your thread’s run loop.
Cocoa和Core Foundation 都提供运行循环对象帮助你安装和管理你的线程运行循环。
15、Your application does not need to create these objects explicitly; each thread, including the application’s main thread ,has an associated run loop object.Only secondary threads need to run their run loop explicitly, however.The app of frameworks automatically set up and run the run loop on the main thread as part of the application startup process.
你的应用不需要清晰地创建这些对象,每个线程,包括应用程序主线程,都有一个与之相关联的run loop对象,不过次要的线程需要清晰地运行它们的循环app 的框架自动设置和运行在主线程的运行循环,这作为应用程序设置流程的一部分。
16、Anatomy of a Run Loop
运行循环详解
It is a loop your thread enters and uses to run event handlers in response to incoming events.Your code provides the control statements used to implement the actual loop portion of the run loop.
它是你的线程进入和使用的循环用来处理事件处理程序,以回应传入的事件。你的码提供控制声明,用来实现运行循环真实的循环部分。
17、In other words ,your code provides the while or for loop that drives the run loop.Within your loop ,you use a run loop object to “run” the event-processing code that receives events and calls the installed handlers.
换句话说,你的码提供while或者for循环来驱使运行循环。在循环的内部,你用一个运行循环对象运行接收事件和调用安装好了的处理程序的事件处理代码。
18、A run loop receives events from two different types of sources. Input sources deliver asynchronous events, usually messages from another thread or from a different application.Timer sources deliver synchronous events ,occurring at a scheduled time or repeating interval .Both types of source use an application-specific handler routine to process the event when it arrives.
一个运行循环从两个不同的源头接收事件,(input sources and timer sources)输入源传递异步的事件,通常是来自己另一个线程或者来自另一个不同的应用的信息,Timer sources 传递同步的事件,发生在一个预定的时间或者重复间隔的时间。当时间到了的时候,两种资源的类型使用一个特殊的处理程序来处理事件。
19、The input sources deliver asynchronous events to the corresponding handlers and cause the runUntilDate: method to exit. Timer sources deliver events to their handler routines but to not cause the run loop to exit
.
20、In addition to handling sources of input ,run loops also generate notifications about the run loop’s behavior.Registered run-loop observers can receive notifications and use them to do additional processing on the thread. You use Core Foundation to install run-loop observers on your threads.
除了处理输入源,运行循环也对运行循环的行为生产通知,注册运行循环观察者能收到通知,用他们做额外的处理。你使用Core Foundation 在你的线程上安装运行循环观察者。A
21、A run loop mode is a collection of input sources and timers to be monitored and a collection of run loop observers to be notified. Each time you run your run loop, you specify (either explicitly or implicitly) a particular “mode” in which to run. During that pass of the run loop, only sources associated with that mode are monitored and allowed to deliver their events. (Similarly, only observers associated with that mode are notified of the run loop’s progress.) Sources associated with other modes hold on to any new events until subsequent passes through the loop in the appropriate mode.
一个运行运行的模式是被监听的传入源和timers的聚集,也是运行循坏的被通知观察者的聚集,每次你执行一个运行循环时,你指定(清晰地或者不清晰地)一个等待执行的特殊模式,在那个运行循环通道里,唯有与那个模式相关联的的资源被监听和被允许传递他们的事件。(同样地,只有与那个模式相关联的观察者才被通知运行循环的进展)。
22、In your code, you identify modes by name. Both Cocoa and Core Foundation define a default mode and several commonly used modes, along with strings for specifying those modes in your code. You can define custom modes by simply specifying a custom string for the mode name. Although the names you assign to custom modes are arbitrary, the contents of those modes are not.在你的代码里,你通过名字确定模式,Cocoa和Core Foundation 定义了一个默认的模式和几种常用的模式,用字符串在代码中指定这些模式,通过指定一个定制的字符串为模型的名字,你能定义一个定制的模型,尽管你赋给这个订制的模式的名字是任意的,但这些模式的内容不是。
23、A modal panel, however, might run in the “modal” mode. While in this mode, only sources relevant to the modal panel would deliver events to the thread. For secondary threads, you might use custom modes to prevent low-priority sources from delivering events during time-critical operations.
对于次要线程,在时序要求严格的操作,你可以使用订制的模式来阻止低优先级的资源传递事件。
24、Modes discriminate based on the source of the event, not the type of the event. For example, you would not use modes to match only mouse-down events or only keyboard events. You could use modes to listen to a different set of ports, suspend timers temporarily, or otherwise change the sources and run loop observers currently being monitored.
模式区分基于事件的资源,而不是事件的类型,举个例子,你将不会用模式来匹配鼠标事件还是键盘事件,你能用modes来听一组不同的端口,临时挂起timer,或者改变这些资源和正被监听的运行时观察者。
25、Default ———> NSDefaultRunLoopMode
The default mode is the one used for most operations.Most oft the time, you should use this mode to start your run loop and configure your input source .
默认模式是一种被大多数操作使用的模式,大部分时间,你应该使用这种模式开始你的运行循环,然后安装你的输入源。
25、Connection ——>NSConnectionReplyMode
Cocoa用这个模式结合NSConnection对象来管回复,这总模式很少使用
26、Modal —>NSModalPanelRunLoopMode
Cocoa 使用这个模式来鉴别想要modal panels的事件。
27、Event tracking —>NSEventTrackingRunLoopMode
Cocoa使用这个模式来限制在鼠标拖拽循环和其他类型的用户接口追踪循环是的传入事件。
28、Common modes ——> NSRunloopCmmonModes
This is a configurable group of commonly used modes. Associating an input source with this mode also associates it with each of the modes in the group. For Cocoa applications, this set includes the default, modal, and event tracking modes by default. Core Foundation includes just the default mode initially.You can add custom modes to the set using theCFRunLoopAddCommonMode function.
AAA
29、Input Sources
(1)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.
基于port的输入源监管你应用的mach 端口,定制的输入源监管你定制的事件源,至于运行循环,它不管输入源是基于端口还是定制的。
(2)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 anther thread.
在两个源之间唯一的区别是他们是怎么标记的,基于端口的源会自动有内核来标记,定制的源必须人为的被另一个线程标记。
(3)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.
当你创建一个输入源的时候,你赋给你的运行循环一个或者多个modes,在任何赋值的时候,modes直接影响哪个源被监管,大部分时间,你运行你的运行循环以一种默认的方式,但你能指定模式,如果一个输入源不是在面前监管的模型里,任何监管源形成事件将被抬起知道运行循环执行正确的模型。
30、Port-Based Sources
Cocoa and Core Foundation provide built-in support for creating port-based input sources using port-related objects and functions.
Cocoa 和Core Foundation 通过使用基于端口的对象和函数来给创建基于端口的输入源提供内置的支持。
31、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 of NSPort to add that port to the run loop.The port object handles the creation and configuration of the needed input source for you.
举例来说,你从不需要直接地创建一个输入源,你只要简单的创建一个端口对象,然后使用NSPort里面的方法来将端口加入运行循环,这个端口对象处理对你需要的端口资源的创建和配置。
32、Custom input Sources
To create a custom input source, you must use the functions associated with theCFRunLoopSourceRefopaque 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.
为了创建一个定制的输入类型,你必须使用与函数相关的core foundation内透明的类型。你通过使用几个回调函数配置一个定制的输入源,Core Foundation 在不同的点调用这些函数去配置这些资源,处理任何输入事件,并且当它被从运行循环中移除时,这些函数能移除资源。
33、In addition to defining the behavior of the custom source when an event arrives, you must also define the event delivery mechanism.
当一个事件到来之时,除了你需要定制资源的行为外,你也必须定制事件交付装置。
34、 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.
这些资源的这部分(事件传递装置)在不同的线程上面运行并且负责给输入源提供它的数据,并且当数据准备处理的时候告诉它,事件传递装置是给你,但没必要过度使用。
35、In addition to port-based sources, Cocoa defines a custom input source that allows you to perform a selector on any thread.
除了基于端口的源,Cocoa定义了一种定制的源,这种源允许在任何线程执行一个方法选择器。
36、Like a port-based source ,perform selector requests are serialized on the target 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 the thread.
像基于端口的资源一样,执行方法请求需要在目标的线程上连续,减轻了许多同步的问题,这些问题是可能是多个方法在同一个线程上跑。
37、Unlike a port-based source ,a perform selector source removes itself from the run loop after it performs its selector.
不像基于端口的资源,一个执行选择器的资源会在它执行了他的方法后将它自己从运行循环中移除。
38、Prior to OSX v 10.5, perform selector sources were used mostly to send messages to the main thread, but in OSX v10.5 and later in iOS, you can use them to send messages to any thread.
在10.5直线,执行选择器资源被大部分用来发信息给主线程,但是在10.5以及10.5之后,你可以用他们给任何线程发信息。
39、When performing a selector on another thread, the target thread must have an active run loop.
当在另一个线程执行方法选择器时,目标线程必须有一个活跃的运行循环。
40、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 applicatinDidFinishLaunching: 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 .
对于你创建的线程,这意味着你会等直到你的代码清晰地开启运行循环。因为主线程开启它自己的运行循环,然而,一旦应用调用了application....方法后,你就开始呼叫那个线程,运行循环通过这个循环处理所有的所有排序的执行方法选择器,而不是每个迭代就处理一次。
41、performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:
这个也必须在当前线程
42、cancelPreviousPerformRequestsWithTarget取消当前的
43、Timers are a way for a thread to notify itself to do something.
timers就是通知线程做事的一种方法。
44、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.
45、Youcan add run loop observers to apps using Core Foundation.To create a run loop observer, you create a new instance of the CFRunLoopObserverRef opaque type.This type keeps track of your custom callback functions and the activities in which it is interested.
你能用一个Core Foundation加一个运行循环观察者给apps,为了创建一个运行循环观察者,你创建一个新的CFRunLoopObserverRef 模糊的类型的实例,这个类型追踪你定制的回调功能和你感兴趣的活动AAAA
45、Each time you run it ,your thread’s run loop processes pending events and generates notifications for any attached observers.
每次你运行它的时候,你的运行循环处理悬而未决的事件,并且给任何附加的观察者发送通知。
46、
- Notify observers that the run loop has been entered.
- Notify observers that any ready timers are about to fire.
- Notify observers that any input sources that are not port based are about to fire.
- Fire any non-port-based input sources that are ready to fire.
- If a port-based input source is ready and waiting to fire, process the event immediately. Go to step 9.
- Notify observers that the thread is about to sleep.
- Put the thread to sleep until one of the following events occurs:
- An event arrives for a port-based input source.
- A timer fires.
- The timeout value set for the run loop expires.
- The run loop is explicitly woken up.
- Notify observers that the thread just woke up.
- Process the pending event.
- If a user-defined timer fired, process the timer event and restart the loop. Go to step 2.
- If an input source fired, deliver the event.
- If the run loop was explicitly woken up but has not yet timed out, restart the loop. Go to step 2.
- Notify observers that the run loop has exited.
1、通知观察者运行循环已经进来了
2、通知观察者任何准备的timers将要启动了
3、告诉观察者任何非基于端口的输入源将要启动了
4、启动任何非基于端口并准备启动的输入源
5、如果一个基于端口的输入源准备和等待启动,那么立即处理这个事件,那么立即跳到第九步
6、通知观察者这个线程将要睡觉了。
7、直到下面的事件的一件发生,线程就不能睡了。
(1)基于端口的输入源事件到了
(2) a timer 启动了
(3)给运行循环设置的超时值失效
(4)运行循环被清晰地唤醒
8、告诉观察者线程醒了
9、Process the pending event
- If a user-defined timer fired, process the timer event and restart the loop. Go to step 2.
- If an input source fired, deliver the event.
- If the run loop was explicitly woken up but has not yet timed out, restart the loop. Go to step 2.
(1)如果一个用户定义的timer 启动了,处理这个timer事件,重启循环,回到第二步骤
(2)如果一个输入源启动了,传递这个事件
(3)如果运行循环运行循环已经被清晰的唤醒,但是还没有超时,重启这个循环,回到步骤2
10、通知观察者运行循环已经退出了。
47、Because observer notification for timer and input sources are delivered before those events actually occur, there may be a gap between the time of the notifications and the time of actual events.
因为对于timer 和输入源的观察者通知在这些时间真实发生之前被传递,在通知的时间和真实时间有一个差距,48、If the timing between these events is critical, you can use the sleep and awake-from-sleep notifications to help you correlate the timing between the actual events.
AAAAA
49、Because timers and other periodic events are delivered when you run the run loop, circumventing that loop disrupts the delivery of those events.
因为timer和其他定期的事件在你运行运行循环时被传递过来,包围那个循环将会打断这些时间的传递。
50、The typical example of this behavior occurs whenever you implement a mouse-tracking routine by entering a loop and repeatedly requesting events from the application. Because your code is grabbing events directly, rather than letting the application dispatch those events normally, active timers would be unable to fire until after your mouse-tracking routine exited and returned control to the application.
这种行为的经典的例子发生,当你通过进入一个循环以及反复地从应用程序请求事件实现一个鼠标追踪程序时,因为你的码直接地抓事件,而不是让应用正常的调度这些事件,活跃的timers将不可能开启,直到你的鼠标追踪程序退出,然后返回控制给应用。
51、When would you use a run loop?
(1)The only time you need to run a run loop explicitly is when you create secondary threads for your application.
唯一的时间你需要很清晰运行一个运行时的是你为你的应用创建一个次要的线程的时候。
(2)The run loop for your application’s main thread is a crucial piece of infrastructure.
你应用的主线程的运行循环是有一个重要的结构。
(3)
if you use a thread to perform some long-running and predetermined task, you can probably avoid starting the run loop. Run loops are intended for situations where you want more interactivity with the thread. For example, you need to start a run loop if you plan to do any of the following:
- Use ports or custom input sources to communicate with other threads.
- Use timers on the thread.
- Use any of the performSelector… methods in a Cocoa application.
- Keep the thread around to perform periodic tasks.
如果你使用一个线程执行长期和预定的任务,你能避免开启运行循环,运行循环在那些你想与线程更多交互的情形,例如,下面的情形就应该用
(1)使用端口或者定制的输入源跟其他线程进行交流的时候
(2)在线程上使用timers的时候
(3)在cocoa应用中使用performSelector方法任何的时候
(4)保持线程在那儿,完成定期的任务。
52、Before you run a run loop on a secondary thread, you must add at least one input source or timer to it. If a run loop does not have any sources to monitor, it exits immediately when you try to run it
在你在第二个线程上运行一个运行循环时,你必须至少一个输入源或者timer给它,如果一个运行循环没有任何资源用来监管,这个运行循环在当你尝试运行它的时候会立即退出。
53、In addition to installing sources, you can also install run loop observers and use them to detect different execution stages of the run loop.
除了安装源,你也能安装运行循环观察者并且使用它们辨别运行循环的不同执行阶段。
54、To install a run loop observer, you create a CFRunLoopObserverRef opaque type and use the CFRunLoopAddObserver function to add it to your run loop.Run loop observers must be created using Core Foundation, even for Cocoa applications
为了安装一个运行循环观察者,你应该创建一个CFRunLoopObserverRef模糊类型,并且用CFRunLoopAddObserver 函数加到你的运行循环。运行循环观察者必须用CoreFoundation 创建,即使为Cocoa 应用。
55、When configuring the run loop for a long-lived thread, it is better to add at least one input source to receive messages.
为了配置一个长期存活的运行循环,最好是至少加一个输入源用来收集信息。
56、Although you can enter the run loop with only timer attached ,once the timer fires ,it is typically invalidated, which would then cause the run loop to exit.
尽管你通过一个timer附上能进入运行循环,可是只要这个timer一启动(这里应该是那种不重复的runloop),这个运行运行里面失效,这种情况会引起运行循环的退出。
57、Attaching a repeating timer could keep the run loop running over a longer period of time, but would involve firing the timer periodically to wake your thread, which is effectively another form of polling.By contrast ,an inout source waits for an event to happen, keeping your thread asleep until it does.
粘附一个重复的timer能让运行循环执行很长一段时间,但是会周期性的参与启动这个timer唤醒你的线程,这是另外一种形式的轮询,相反,一个输入源会等一个事件发生,在事件发生之前会一直处于休眠状态。
58、Starting the run loop is necessary only for the secondary threads in your application. A run loop must have at least one input source or timer to monitor. If one is not attached, the run loop exits immediately.
为你的第二个线程开启运行循环是必要的,一个运行循环至少得有一个输入源或者timer来监管,如果一个没有附加上,运行循环立马退出。
59、There are several ways to start the run loop, including the following.
- Unconditionally
- With a set time limit
- In a particular mode AAAAA
60、intering your run loop unconditionally is the simplest option, but it is also the least desirable. Running your run loop unconditionally puts the thread into a permanent loop, which gives you very little control over the run loop itself. You can add and remove input sources and timers, but the only way to stop the run loop is to kill it. There is also no way to run the run loop in a custom mode.
无条件的进入你的运行循环是最简单的选择,但是也是最不可取的。无条件的运行你的运行循环会使这个线程进入永久性循环,这会给你对运行循环很小的控制,你能添加或者移除输入源和timers,但是停止这个运行循环的唯一方式是杀掉它。在定制的模式下,也没有方式来运行这个运行循环。
61、Instead of running a run loop unconditionally, it is better to run loop with a timeout value.
最好用一个超时值来运行运行循环,而不是无条件的运行一个运行循环。
62、When you use a timeout value, the run loop runs until an event arrives or the allotted time expires.
当你用一个超时值时,当事件来临或者分配的时间终止时运行循环结束。
63、If an event arrives ,that event is dispatched to handler for processing and then the run loop exits.
当一件事件来临时,这个事件被分派给一个处理器处理,然后运行循环退出。
64、Your code can then restart the run loop to handle the next event.
你的码能重启你的运行循环来处理下一个事件
65、If the allotted time expires instead, you can simply restart the run loop or use the time to do any needed housekeeping。 AAAAA
66、In addition to a timeout value, you can also run your run loop using a specific mode.Modes and timeout values are not mutually exclusive and can both be used when starting a run loop. Modes limit the types of sources that deliver events to the run loop
除了设置一个超时值,你能通过一个特殊的模式运行你的运行循环,模式和超时值不是互联排斥的,当开启一个运行循环的时候,他们都能同时使用。模型限制了传递时间给运行循环的资源的类型。
67、It is possible to run a run loop recursively. In other words, you can callCFRunLoopRun, CFRunLoopRunInMode, or any of the NSRunLoopmethods for starting the run loop from within the handler routine of an input source or timer. When doing so, you can use any mode you want to run the nested run loop, including the mode in use by the outer run loop.
68、退出运行循环。
There are two ways to make a run loop exit before it has processed an event.
- Configure the run loop to run with a timeout value.
- Tell the run loop to stop.
配置一个运行循环用一个超时值
告诉运行循环停止
69、Stopping the run loop explicitly with the CFRunLoopStop function produces a result similar to a timeout .The run loop sends out any remaining run-loop notifications and then exits.The difference is that you can use this technique on run loops you started unconditionally.
用CFRunLoopStop函数清晰地停止运行循环会产生一个类型timeout的结果,这个运行循环发出任何遗留的运行循环通知二退出,区别是,你只能在你无条件启动的运行循环上使用这个技术。
70、Although removing a run loop’s input sources and timers may also cause the run loop to exit, this is not a reliable way to stop a run loop. Some system routines add input sources to a run loop to handle needed events. Because your code might not be aware of these input sources, it would be unable to remove them, which would prevent the run loop from exiting.
AAAA
71、The functions in Core Foundation are generally thread-safe and can be called from any thread.If you are performing operations that alter the configuration of the run loop, however, it is still good practice to do so from the thread that owns the run loop whenever possible.
If(in cocoa) you are using the NSRunLoop class to modify your run loop , you should do so only from the same thread that owns that run loop
在cf里面的函数通常是线程安全的,他们能被任何线程调用,但是,如果你执行操作来改变运行循环的配置,尽可能选择那个拥有那个运行循环的线程仍是一种好的做法。
在Cocoa中,如果你用NSRunLoop类来修改你的循环,你应该只能从那个拥有运行循环的线程中这么做。
72、Adding an input source or timer to a run loop belonging to a different thread could cause your code to crash or behave in an unexpected way.
给一个属于不同线程的运行循环加一个输入源或者timer能引起你的代码crash,或者行为异常。
73、配置运行循环。
Creating a custom input source involves defining the following:
- The information you want your input source to process.
- A scheduler routine to let interested clients know how to contact your input source.
- A handler routine to perform requests sent by any clients.
- A cancellation routine to invalidate your input source.
创建一个定制的输入源,你要定义下面的
(1)信息你想要你的输入源处理的
(2)一个调度程序让有兴趣的客户端知道怎么联系你的输入源
(3)一个处理程序来完成客户发送的请求
(4)一个取消程序来使你的输入源无效
74、The scheduler, handler ,and cancellation routines are the key routines you almost always need for your custom input source.
调度程序处理程序取消程序是你必须总是为你的定制的输入源准备的程序。
75、Most of the rest of the input source behavior ,however ,happens outside of those handler routines.For example ,it is up to you to define the mechanism for passing data to your input source and for communicating the presence of your input source to other threads.
然后输入源的大部分行为发生在这些处理程序的外边,举个例子,定义传递数据的装置给你的输入源,以及让你的输入源和其他线程进行交流这些取决于你。
76、The RunLoopSource object manages a command buffer and uses that buffer to receive messages from other threads.
RunLoopSource对象管理一个命令缓冲器,使用这个缓冲器从其他线程接收信息。
77、installing the run loop source
- (id)init
{
CFRunLoopSourceContext context = {0, self, NULL, NULL, NULL, NULL, NULL, &RunLoopSouceScheduleRoutine, RunLoopSouceCancelRoutine, RunLoopSourcePerformRountine};
runLoopSouce = CFRunLoopSourceCreate(NULL, 0, &context);
commands =[ [NSMutableArray alloc] init];
return self;
}
- (void)addToCurrentRunloop {
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode);
}
第二次学习:
runloop经典文章:
https://blog.ibireme.com/2015/05/18/runloop/
1、所以Runloop实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行上面Event Loop的逻辑。
2、OSX/iOS 系统中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef。
CFRunLoopRef 是在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的。
3、NSRunLoop 是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的。
4、从上面的代码可以看出,线程和 RunLoop 之间是一一对应的,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。
5、有时你需要一个 Timer,在两个 Mode 中都能得到回调,一种办法就是将这个 Timer 分别加入这两个 Mode。还有一种方式,就是将 Timer 加入到顶层的 RunLoop 的 “commonModeItems” 中。”commonModeItems” 被 RunLoop 自动更新到所有具有”Common”属性的 Mode 里去。
6、CFRunloop对外暴露的管理Mode接口只有下面2个:
CFRunLoopAddCommonMode(CFRunLoopRef runloop, CFStringRef modeName);//加模式
CFRunLoopRunInMode(CFStringRef modeName, …) //给模型命名
7、Mode暴露的管理 mode item的接口有下面几个
给特定运行循环,添加模式和名字
CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopAddObserver(CFRunLoopRef r1,CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopAddTimer(CFRunLoopRef r1,CFrunLoopTimerRef timer, CFStringRef mode);
移除有特定模式和名字的特定运行循环
CFRunLoopRemoveSource(CFRunLoopRef r1 ,CFRunloopSourceRef source, CFStringRef modeName);
CFRunLoopRemoveObserver(CFRunLoopRef r1,CFRunloopObserverRef observer, CFStringRef modeName);
CFRunloopRemoveTimer(CFRunLoopRef r1, CFRunLoopTimerRef timer, CFStringRef mode);
8、我对运行循环的理解是:1、模式提供五个,但公开的mode有两个也就是kCFRunLoopDefaultMode(NSDefaultRunLoopMode)和UITrackingRunLoopMode