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 *