一、文档原文
Description: Invokes a method of the receiver on the current thread using the default mode after a delay.
This method sets up a timer to perform the aSelector
message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode
). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.
If you want the message to be dequeued when the run loop is in a mode other than the default mode, use the performSelector: withObject:afterDelay:inModes: method instead. If you are not sure whether the current thread is the main thread, you can use the performSelectorOnMainThread:withObject:waitUntilDone: or performSelectorOnMainThread:withObject:waitUntilDone: modes: method to guarantee that your selector executes on the main thread. To cancel a queued message, use the cancelPreviousPerformRequestsWithTarget: or cancelPreviousPerformRequestsWithTarget:selector:object:method.
Parameters:
aSelector: A selector that identifies the method to invoke. The method should not have a significant return value and should take a single argument of type id
, or no arguments.
anArgument:The argument to pass to the method when it is invoked. Pass nil
if the method does not take an argument.
delay: The minimum time before which the message is sent. Specifying a delay of 0 does not necessarily cause the selector to be performed immediately. The selector is still queued on the thread’s run loop and performed as soon as possible.
二、文档解析
1)This method sets up a timer to perform…
What:此处的timer不是Foundation库中的NSTimer,而是Core Foundation库中的一个结构体:struct __CFRunLoopTimer。
Why:为什么再这里强调一下呢?因为若理解成NSTimer的话,会引起一系列的矛盾。此处不做展开详述,后续再续。
(比如:NSTimer本身时间度量不准确性与aSelector被执行时相对准确性的矛盾、NSTimer没有Enqueue、Dequeue概念与__CFRunLoopTimer有Enqueue、Dequeue概念等)
2)The timer is configured to run in the default mode (NSDefaultRunLoopMode
).
What:此处configure是只有底层内部创建timer,不需要上层开发人员参与。
Why:因为要保证runloop的正常运行逻辑,CFRunloop基本上不允许上层开发参与定制,只允许使用。此处涉及方法为:CFRunLoopAddTimer。
此处不做展开详述,后续再续。
What:此处NSDefaultRunLoopMode,因此在使用时不要联合使用涉及Mode的方法,除非你特别清除Mode各种情况,即便是main thread也是一样。(比如:GCD、NSObject delay perform中涉及mode的方法)
Why:因为Mode会涉及到runloop的mode切换(平行切换、嵌套切换)、defaultMode与CommonMode的区别联系。此处不做展开详述,后续再续。
3)When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector
What:本质上是__CFRunLoopTimer从_timers(_timers属于__CFRunLoopMode的结构体成员)中被dequeue,
然后调用_callout(_callout是__CFRunLoopTimer的结构体成员),进而实现调用Selector。
Why:上述逻辑都是在runloop内部实现的,对外是不可见。此处不做展开详述,后续再续。
4)The method should not have a significant return value……
Why:who tell me why????
5)Specifying a delay of 0 does not necessarily cause the selector to be performed immediately
What:由3)可知只有__CFRunLoopTimer被dequeue时,Selector才能得到被执行。那么__CFRunLoopTimer是何时被dequeue的呢?
总所周知:runloop是个运行环,假设执行环路线逻辑是:A-->B-->C-->D-->A,B点是__CFRunLoopTimer被dequeue。
如果CFRunLoopAddTimer在B点之前执行,则B会在本runloop周期内执行。
如果CFRunLoopAddTimer在B点之后执行,则B会在下一个runloop周期内执行。此处不做展开详述,后续再续。
因此也就能理解:
The minimum time before which the message is sent.
The selector is still queued on the thread’s run loop and performed as soon as possible.