RunLoop is abstract and hard to understand, so watch it a few times to learn it well! This is also an advanced iOS must master knowledge, often encountered in the interview.

What is RunLoop?

Run means to Run and Loop means to Loop. Put together, it means to run a cycle. A RunLoop is a loop that does something while the program is running.

What are the applications of RunLoop?

Timer, PerformSelector

GCD Async Main Queue

Event response, gesture recognition, interface refresh

Network request

AutoreieasePool

All of these are supported by Runloops, and frankly, none of these would be possible without RunLoop support.

What would happen if there were no RunLoop? Like our command line project, it is created without RunLoop by default, as shown below

Since there is no RunLoop, the program will exit automatically at line 13.

UIApplicationMain(argc, argV,nil, appDelegateClassName) in our iOS project main; This code, here is a RunLoop that creates a main thread, so our program doesn’t exit, it just keeps running. The pseudocode inside main can be written as follows:

RetVal =0, RunLoop will sleep when no event is being handled, process_message will process the event once there is an event to be handled, such as a click, refresh event, etc., and will continue to rest after processing,retVal=0, and the program will continue executing without exit That’s what RunLoop does.

The basic functions of RunLoop

1. Keep the program running

2. Handle various events in App (such as touch events, timer events, etc.)

3. Save CPU resources, improve program performance: work when the work, the rest of the rest


Get the RunLoop object

There are two apis in iOS to access and use RunLoop:

Foundation: NSRunLoop

Core Foundation: CFRunLoopRef

Both NSRunLoop and CFRunLoopRef represent RunLoop objects

NSRunLoop is a layer of OC wrapper based on CFRunLoopRef

CFRunLoopRef is open source.

In fact, many of us are packaged by OC, please see the following:

Gets the current RunLoop

Get the current RunLoop and the main thread RunLoop

Get RunLoop

Note that the address is different because NSRunLoop is wrapped around CFRunLoopDef. You can use the OC NSLog(“%@”,[NSRunLoop MainRunLoop]) to get its address. The main thread has only one RunLoop.

RunLoop with thread

Each thread has a unique RunLoop object corresponding to it (one to one)

Runloops are stored in a global Dictionary, with threads as keys and runloops as values

The thread does not have a RunLoop object when it is first created. The RunLoop is created when it first retrieves it

The RunLoop is destroyed at the end of the thread

The RunLoop for the main thread is created automatically, and RunLoop is not enabled for the child thread by default.

Source code :CFRunLoopGetCurrent

Since the source code cannot be opened directly like objC, we pull it into the project to view.

And you can see from the dictionary that it’s a one-to-one relationship. And it is true that the first fetch is empty, and then the RunLoop is created.

Let’s move on to understand how the data structure inside RunLoop actually works.

Runloop-related classes

Five classes for RunLoop in Core Foundation

1.CFRunLoopRef

2.CFRunLoopModeRef

3.CFRunLoopSourceRef

4.CFRunLoopTimerRef

5.CFRunLoopObserverRef

CFRunLoopRef = CFRunLoopRef

Pthreads are threads that are stored in each runloop. The last _modes, this is a set,CFMutableSetRef we can think of our own set is a set, such as NSMutableSet is a set, so there are a bunch of modes in this _modes.

This mode is CFRunLoopModeRef, so it stores a bunch of CFRunLoopModeRef modes.

Currentmode is also CFRunLoopModeRef, so it’s easy to conclude:

A RunLoop object has a bunch of modes in it, that is, _modes, and only one of them is _currentMode.

Let’s take a look at the source code and see what mode stores.

So here’s a summary:

RunLoop has many modes, but only one corresponding _currentMode.

CFRunLoopModeRef

1.CFRunLoopModeRef Represents the running mode of RunLoop

2. A RunLoop contains several Mode, each Mode and contains several Source0 / Source1 / Timer/Observer

3. Only one Mode can be selected as currentMode when RunLoop starts

4. To switch Mode, exit the current RunLoop and select another Mode

5. Different groups of Source0 / Source1 / Timer/Observer can be separated, each other

6. If there is no any Source0 Source1 / Mode inside the Timer/Observer, RunLoop immediately exit

If you can only run it in one mode, it’s really good for performance and all that stuff, like if I’m in slide mode, I don’t think about non-slide mode, so it doesn’t get stuck, it gets a lot smoother. Also note that it switches mode inside the loop, so it does not cause the program to exit.

There are two common modes, and few others, so mastering them is generally no problem

1.KCFRunLoopDefaultMode (NSDefaultRunLoopMode): the default Mode of App, usually the main thread runs in this Mode

2.UITrackingRunLoopMode: interface tracking Mode, used for ScrollView tracking touch sliding, to ensure that the interface sliding is not affected by other modes

What exactly does RunLoop do?

What exactly does a RunLoop do when it’s executing continuously? RunLoop: Source0, Source1, Timer, Observer for each mode

Source0

Touch events, performSelector: onThread:

For example, with our touchBegin, let’s look at the following code:

Source1

Port – based communication between threads, system event capture.

(The process of passing messages between two threads, system event capture, which actually includes touch events, is captured and passed to Source0).

Timer

NSTimer timer, performSelector: withObject: afterDelay (the underlying implementation of this method is also implemented NSTimer)

Observers

Listen for RunLoop state,UI refresh (BeforeWaiting),Autorelease pool(BeforeWaiting)

(UI refresh, Autorelease pool release, etc.)

All of these things are exactly the same code that we usually write during development, such as setting the background color, setting the frame and so on.