Why does NSTimer sometimes not work?

Since the created NSTimer is added to defaultMode by default, when the Mode of Runloop changes

When, the current NSTimer will not work.

How to use Runloop in AFNetworking?

Before RunLoop starts, there must be at least one Timer/Observer/Source, so AFNetworking creates a new NSMachPort and adds it to it before [RunLoop run]. Normally, the caller needs to hold this NSMachPort (mach_port) and send messages inside the loop through this port from the external thread; But port is added here only to keep the RunLoop from exiting, not to actually send messages.

AFNetworking calls the background thread when it is needed to perform a task

[NSObject performSelector:onThread:..] Throw the task to the RunLoop of the background thread

When is autoreleasePool released?

After the App starts, Apple registers two observers in the main RunLoop

The callback is _wrapRunLoopWithAutoreleasePoolHandler ().

The first Observer monitors an event, Entry (about to enter Loop), which is called within the callback

_objc_autoreleasePoolPush() creates an automatic release pool. Its order is -2147483647, priority

Ensures that the release pool is created before all other callbacks.

The second Observer monitors two events: called when waiting (ready to go to sleep)

_objc_autoreleasePoolPop() and _objc_autoreleasePoolPush() free the old pool and create it

The new pool; Call _objc_autoreleasePoolPop() on Exit (about to Exit Loop) torelease the automatic release

Pool. The order of this Observer is 2147483647, which has the lowest priority and ensures that its release pool occurs in

After all the other callbacks.

The code that executes on the main thread is usually written inside such callbacks as event callbacks and Timer callbacks. These callbacks are going to be

The AutoreleasePool created by RunLoop is wrapped around, so there is no memory leak, and neither is the developer

A Pool must be created.

PerformSelector: afterDelay: this method is in the child thread work? Why is that? How to solve it?

It doesn’t work. The child thread has no Runloop by default and therefore no Timer.

The solution is to use GCD: Dispatch_after

The RunLoop Mode

The first thing you need to know about modes is that a RunLoop object can contain multiple modes and that RunLoop is called each time

Only one Mode(CurrentMode) can be specified. To switch Mode, specify a new one

A Mode. The main purpose is to separate different sources, timers, and observers from each other

Impact. It is not acceptable to handle Mode2 or Mode3 while RunLoop is running on Mode1

The Source ̵ Timer ̵ Observer events

There are five types of CFRunLoopMode:

  • KCFRunLoopDefaultMode: The default mode in which the main thread runs
  • UITrackingRunLoopMode: tracking user interaction events (for ScrollView tracking touch slides,

Ensure that the interface is not affected by other modes when sliding)

  • UIInitializationRunLoopMod: in the first to enter the first Mode when just start the App, start to the end

And then it’s not used anymore

  • GSEventReceiveRunLoopMode: accept system internal event, is usually not used
  • Kcfrunloopcommonmode: pseudo-mode, not a true operation Mode, is a solution for synchronizing Source/Timer/Observer modes into multiple modes

RunLoop implementation mechanism

The core thing for RunLoop is to ensure that threads sleep when there is no message and call when there is one

Wake up to improve program performance. RunLoop is a mechanism that relies on the kernel (Apple OPERATING System core)

Mach in Darwin for heart components).

RunLoop receives and sends messages using the mach_msg() function. Its essence is to call a function

Mach_msg_trap (), which acts as a system call, triggers a kernel state switch. Call in user mode

Mach_msg_trap () will switch to kernel mode; The mach_msg() function implemented by the kernel completes in the kernel state

The actual work.

The port-based source1 listens on the port and triggers a callback if there is a message on the port. Source0, on the other hand

Move marks for pending and manual wake up RunLoop

The general logic is:

1. Notify the observer that RunLoop is about to start.

2. Notify the observer that the Timer event is about to be processed.

Notify the observer that the source0 event is about to be processed.

4. Handle the source0 event.

5. If the port-based source (Source1) is ready and in the waiting state, go to Step 9.

6. Notify the observer that the thread is about to go to sleep.

7, put the thread to sleep, switch from user mode to kernel mode, and do not wake up until any of the following events occur

Cheng.

  • A port-based Source1 event (source0).
  • A Timer is out of time.
  • RunLoop’s own timeout is up.
  • Manually awakened by another caller.

8. Notify the observer that the thread will wake up.

9. Handle events received upon awakening.

  • If the user-defined timer starts, process the timer event and restart RunLoop. Go to Step 2.
  • If the input source is started, the corresponding message is passed.
  • If RunLoop is awakened and the time has not expired, restart the RunLoop. Enter Step 2.

10. Notify the observer of the end of RunLoop.

How do I create a resident thread?

1. Start a RunLoop for the current thread (when the [NSRunLoop currentRunLoop] method is first called)

Create a RunLoop first.

2. Add a Port/Source or other event loop to the current RunLoop (if

RunLoop mode has no item, RunLoop exits.

3. Start the RunLoop

RunLoop data structure

NSRunLoop(Foundation) is an encapsulation of CFRunLoop(CoreFoundation) and provides object-oriented

API

RunLoop is related to five classes:

CFRunLoop: RunLoop object

CFRunLoopMode: indicates the running mode

CFRunLoopSource: input source/event source

CFRunLoopTimer: indicates the timing source

CFRunLoopObserver: observer

1, CFRunLoop

Pthread (thread object, meaning RunLoop and thread are one-to-one counterpart), currentMode(current position)

), modes (a collection of modes), commonModes (a collection of mode name strings),

CommonModelItems (Observer,Timer,Source collection)

2, CFRunLoopMode

By the name ̵ source0 ̵ source1 ̵ observers ̵ timers

3, CFRunLoopSource

There are source0 and source1

source0:

That is, non-port-based events, which are user-triggered events. You need to wake up the thread manually to remove the current thread from kernel state

Switch to user mode

source1:

Port-based, containing a mach_port and a callback, listening on system ports and through the kernel and other lines

The procedure sends a message that actively wakes up the RunLoop to receive distribution system events. Ability to wake up threads

4, CFRunLoopTimer

Time-based triggers are basically NSTimer. Wake up the RunLoop at a preset point in time

Adjustable. Since it is runloop-based, it is not real-time (i.e. NSTimer is inaccurate). Due to the

The RunLoop is only responsible for distributing messages from the source. This can result if the thread is currently processing heavy tasks

Timer Indicates the time delay, or less than one time.

5, CFRunLoopObserver

Listen for the following points: CFRunLoopActivity kCFRunLoopEntry: RunLoop ready to start

KCFRunLoopBeforeTimers: RunLoop will handle some timer-related events

KCFRunLoopBeforeSources: RunLoop will handle some Source events kCFRunLoopBeforeWaiting: RunLoop will go to sleep, switching from user state to kernel state

KCFRunLoopAfterWaiting: The RunLoop is awakened after switching from the kernel state to the user state

KCFRunLoopExit: RunLoop exits

KCFRunLoopAllActivities: Listens for all states

6. Relationships between data structures

Threads correspond to runloops one by one, RunLoop and Mode are one-to-many, Mode and source and timer

The Observer is also one-to-many

Explain NSTimer

NSTimer is essentially a CFRunLoopTimerRef. It’s toll-free bridged between them. a

After NSTimer registers with RunLoop, the RunLoop registers events for its repeated time points. For example,

10:00, 10:10, 10:20. RunLoop will not be very accurate in order to save resources

Time point callback this Timer. Timer has a property called Tolerance that identifies time

What is the maximum allowable error after the dot arrives.

\

If a point in time is missed, such as a long task, the callback at that point in time will also jump

In the past, there was no delay. Like waiting for the bus, if I’m busy with my phone at 10:10 and I miss the bus at that time

Yes, I’ll have to wait for the 10:20.

\

CADisplayLink is a timer with the same refresh rate as the screen (but the actual implementation principle is more complicated, and

NSTimer is different in that it actually operates on a Source. If it’s between screen refreshes

When a long task is executed, one frame will be skipped (similar to NSTimer), causing the interface to stall

Feeling. Even a frame stalling is noticeable to the user when swiping a TableView quickly. Facebook open source

AsyncDisplayLink is designed to solve the problem of interface lag, and it also uses RunLoop internally

Explain the process of event response?

Apple has registered a Source1 (Mach Port-based) to receive system events and its callback function is

__IOHIDEventSystemClientQueueCallback ().

When a hardware event (touch/lock/shake, etc.) occurs, IOKit. Framework first generates one

The IOHIDEvent event is received by the SpringBoard. Details of this process can be found here.

SpringBoard only receives several events along with buttons (lock screen/mute etc.), touch, acceleration, proximity sensor etc

Then Mach port is used to forward to the required App process. Then apple registered the Source1 will trigger the callback, and call the _UIApplicationHandleEventQueue () distribution within the application.

_UIApplicationHandleEventQueue () will take IOHIDEvent processing and packaging into UIEvent

Processing or distribution, including identification of UIGesture/॒ቘ੽଒෤᫨/ݎᭆᕳ UIWindow, etc. Common event ratio

Such as a UIButton click, touchesBegin/Move/End/Cancel events are done in the middle of this callback.

Explain the process of gesture recognition?

When the above _UIApplicationHandleEventQueue () to identify a gesture, the first call

Cancel interrupts the current touchesBegin/Move/End series callbacks. Then the system will correspond to

UIGestureRecognizer is marked as pending.

Apple has registered an Observer to monitor BeforeWaiting (Loop about to go to sleep) events, this one

The Observer callback function is _UIGestureRecognizerUpdateObserver (), its internal will get

GestureRecognizer has just been marked as pending and executes the GestureRecognizer callback.

Whenever there is a change to the UIGestureRecognizer (create/destroy/state change), this callback is applied accordingly

To deal with.

Explain the page rendering process using runloop.

When we call [UIView setNeedsDisplay], we call the current view.layer

Layer setNeedsDisplay method.

This is equal to placing a dirty mark on the current layer without drawing directly. But will

Drawing is not done until the current Runloop is about to sleep, which is beforeWaiting.

This is followed by a call to the [CALayer display] to do the actual drawing. The CALayer layer judges itself

The delegate does not implement the asynchronously drawn delegate method displayer:, which is asynchronously drawn

If this method is not implemented, the process of system drawing continues, and then the knot is drawn

Beam.

A Backing Store is created inside CALayer to get the graphics context. And we’re going to figure this out

Whether the layer has a delegate.

If so, [layer.delegate drawLayer:inContext:] will be called and returned to us

[UIView DrawRect:], let’s do a few more things on top of the system drawing.

If there is no delegate, then [CALayer drawInContext:] is called.

In both cases, CALayer will eventually commit the bitmap to the Backing Store and then to the GPU.

This is the end of the drawing process.

What is asynchronous drawing?

Asynchronous drawing, is the need to draw in the child thread graphics, in advance in the child thread processing. Will be ready

Image data is returned directly to the main thread to reduce the stress on the main thread.

The process of asynchronous drawing

Asynchronous drawing is done through the system’s [view.Delegate displayLayer:] entry.

The proxy is responsible for generating the corresponding Bitmap

Set this Bitmap to the value of the layer.contents property

conclusion

As a serious Python enthusiast, the above are some of my own experiences and materials to share. Welcome your comments and comments, and I hope they can be helpful to Meng Xin. Incidentally for a wave of attention, need to learn information \ and consulting programming problems of the students, you can click * to get information *