An overview of the

What is the RunLoop

Run Loop: As the name implies, runloop is a kind of Loop. Unlike other loops, runloop is a kind of idle Loop. If there is no event, runloop goes to sleep, otherwise it finds the corresponding handler. The Run Loop receives events of two different types of resources, Input/Timer sources.

Runloops are tied to threads. Each thread, including the main thread, has a corresponding Runloop object. We can’t create Runloop objects ourselves, but we can get Runloop objects provided by the system. The Runloop for the main thread will start when the application starts. The Runloop for the other threads will not start by default and will need to be started manually

Run Loop Modes

RunLoopMode is a collection of monitored resources and observers. Each run of runloop requires a special mode. During the run, only the associated modes are monitored and receive events, that is, there are no modes. Runloop is an event that cannot be handled. Apple has different declarations in Cocoa and Core Foundation, and most of the time we use the system-defined “default” mode directly.

Mode Name Description
Default NSDefaultRunLoopMode (Cocoa), kCFRunLoopDefaultMode (Core Foundation) Runloop can be started in most scenarios
Connection NSConnectionReplyMode Handle events related to NSConnection objects, used internally by the system. This mode indicates that NSConnection objects wait for reply, and users will not use them.
Modal NSModalPaneRunLoopMode To handle modal Panels events, set when the input source waiting to be processed is a Modal Panel, such as NSSavePanel and NSOpenPanel
Event tracking NSEventTrackingRunLoopMode Use this mode to handle user interface related events, such as drag loops or other user interface Tracking loops, where processing of input events is limited. For example, the finger is in this mode when holding down the UITableView drag
Common NSRunLoopCommonModes (Cocoa), kCFRunLoopCommonModes (Core Foundation) This is a pseudo-mode, which is a set of Run Loop Modes. Adding the input source to this mode means that it can be processed in all Modes included in Common Modes. In Cocoa applications, by default Common Modes include default Modes, Modal Modes, Event Tracking Modes, You can use the CFRunLoopAddCommonMode method to add custom Modes to Common Modes

Sources(Input/Timer)

Event source: Target monitoring source that causes RunLoop to wake up the thread when needed and sleep when not

Input Sources

Input sources are mainly asynchronous events, such as messages from other threads or other apps

  • Port-Based SourcesPort events at the bottom of the system, such as CFSocketRef, are rarely used at the application layer
  • Custom Input SourceSource manually created by the user
  • Cocoa Perform Selector SourcesProvided the CocoaperformSelectorSerial methods are also a source of events

Timer Source

Timer events as the name implies. When creating NSTimer to add to the Runloop, it’s important to note that NSTimer is in NSDefaultRunloopMode by default, which explains why if you add a timer to your controller to refresh your interface, And when you drag the view in the timer is not back to the fire, because this time is your runloop NSEventTrackingRunloopMode, the timer is not back to the fire under this mode

Observers

The RunLoop listens to the Source to determine that there are no tasks to be done, but we can also use the RunLoop Observer to monitor the status of the RunLoop itself. You can listen for the following events:

  • The beginning of the RunLoop
  • Timer processing is about to start
  • Source processing is about to begin
  • About to go to sleep
  • To awaken from hibernation
  • Exit the RunLoop

Along with the event being listened for, Runloop also passes the event to the event observer, which, according to Apple’s documentation, goes something like this:

RunLoop and thread

  • Each thread has a unique RunLoop object corresponding to it
  • Main line program view creation, since the thread needs to actively create
  • The RunLoop is created on the first fetch and destroyed at the end of the thread

CFRunLoopGetMain(); CFRunLoopGetCurrent(); CFRunLoopGetCurrent();

// global Dictionary, key is pthread_t, value is CFRunLoopRef
static CFMutableDictionaryRef loopsDic;
// Lock when accessing loopsDic
static CFSpinLock_t loopsLock;

// Get a RunLoop for a pthread.
CFRunLoopRef _CFRunLoopGet(pthread_t thread) {
    OSSpinLockLock(&loopsLock);

    if(! loopsDic) {// On first entry, initialize global Dic and create a RunLoop for the master thread.
        loopsDic = CFDictionaryCreateMutable(a);CFRunLoopRef mainLoop = _CFRunLoopCreate();
        CFDictionarySetValue(loopsDic, pthread_main_thread_np(), mainLoop);
    }

    // Get it directly from the Dictionary.
    CFRunLoopRef loop = CFDictionaryGetValue(loopsDic, thread));

    if(! loop) {// If not, create one
        loop = _CFRunLoopCreate();
        CFDictionarySetValue(loopsDic, thread, loop);
        // Register a callback to destroy the corresponding RunLoop when the thread is destroyed._CFSetTSD(... , thread, loop, __CFFinalizeRunLoop); } OSSpinLockUnLock(&loopsLock);return loop;
}

CFRunLoopRef CFRunLoopGetMain() {
    return _CFRunLoopGet(pthread_main_thread_np());
}

CFRunLoopRef CFRunLoopGetCurrent() {
    return _CFRunLoopGet(pthread_self());
}
Copy the code

application

AutoreleasePool

After the iOS application is launched, two observers are registered to manage and maintain AutoreleasePool.

The UI update

The AsyncDisplayKit, for example, adds an Observer to the main thread RunLoop to listen for both impending sleep and exit RunLoop states, and then loops through the queue of pending tasks in a callback.

GCD

A call to dispatch_async() in GCD sends a message to the main thread’s RunLoop to wake up the RunLoop, but this operation is limited to the main thread. All other thread dispatches are driven by libDispatch

Question and answer

  1. How is a method executed when performing performSelector delayed? Is it the same in child threads?
  2. Are event response and gesture recognition underlying processing consistent? Why is that?
  3. When does the interface refresh, when does the actual refresh occur, and why not in time?
  4. When did the auto-release pool creation and destruction take place?
  5. How do I ensure that the current thread is not destroyed when a child thread needs to execute a callback?

See the iOS RunLoop for details

reference

Get to the bottom of the RunLoop Apple documentation – Get to the bottom of RunLoop

For more information, please follow SwiftOldBird’s official wechat account

From the original: swiftoldbird. Loveli. Site / 2019/08/19 /…