concept
-
Runloop is an object that manages events/messages through an internally maintained event loop.
-
Event loop
-
Sleep when there are no messages to process to avoid resource usage. Switch from user mode to kernel mode.
-
Wake up immediately when a message needs to be processed. Switch from the kernel mode to the user mode.
-
The basic function
- Keep the program running
- Handle various events in the App (such as touch events, timer events, etc.)
- Save CPU resources, improve program performance: work when you should work, rest when you should rest
Q: Why is main guaranteed not to exit?
UIApplicationMain
To start the main threadrunloop
Runloop object
-
Foundation: NSRunLoop
-
The Core Foundation: CFRunLoopRef
CFRunLoopRef
Mode
CFRunLoopModeRef representative RunLoop Mode of running a RunLoop contains several Mode, each Mode and contains several Source0 / Source1 / Timer/Observer, RunLoop startup can only choose one of the Mode, As currentMode. If you need to switch Mode, can only exit from the current Loop, choose a Mode again into different groups Source0 / Source1 / Timer/Observer can be separated, Each other if there is no any Mode Source0 / Source1 / Timer/Observer, RunLoop immediately exit.
When running under mode1, they can only receive and process sources, observers, and timers under Mode1, but cannot receive event callbacks under Mode2 and mode3.
Two common modes
- KCFRunLoopDefaultMode (NSDefaultRunLoopMode) : The default Mode of the App, in which the main thread usually runs
- UITrackingRunLoopMode: interface tracing Mode, used by ScrollView to track touch sliding, ensuring that the interface sliding is not affected by other modes
Q: How do I add a Timer to both modes?
commonMode
Not one that actually existsMode
.- Are synchronous
Source/Timer/Observer
To multipleMode
A technical solution in.
ModeItem
- Source0
- When adding events to
Source0
Instead of actively waking up the thread, you need to wake it up manually. To use this, you need to call CFRunLoopSourceSignal(source), mark the source as pending, and then manually call CFRunLoopWakeUp(runloop) to wake up the Runloop to handle the event.
- When adding events to
- Source1
- Ability to wake up threads. Contains a mach_port and a callback (function pointer) that is used to send messages to each other through the kernel and other threads.
- CFRunLoopTimer
- Event-based timers, and
NSTimer
It’s convertible.
- Event-based timers, and
- CFRunLoopObserver
- Observation time point
kCFRunLoopEntry
Coming to LoopkCFRunLoopBeforeTimers
About to process the TimerkCFRunLoopBeforeSources
About to process SourcekCFRunLoopBeforeWaiting
(User-mode and kernel-mode)kCFRunLoopAfterWaiting
(Kernel mode to user mode)KCFRunLoopExit is about to exit
- Observation time point
Q: Wake up dormant Runloop?
- Source1
- The Timer events
- External manual wake up
Event loop mechanism
RunLoop Event loop mechanism
Inside the RunLoop is a do-while loop. When you call CFRunLoopRun(), the thread stays in the loop forever; This function does not return until it times out or is stopped manually. RunLoop T goes to sleep to wake up by calling mach_msg.
Runloop and thread relationships
- Each thread has a unique RunLoop object corresponding to it
- Runloops are stored in a global Dictionary, with threads as keys and runloops as values
- The thread is created without a RunLoop object; the RunLoop is created the first time it gets it
- The RunLoop is destroyed at the end of the thread
- The RunLoop for the main thread is automatically acquired (created), and RunLoop is not enabled for the child thread by default
Thread safety
- The CFRunLoop family of functions is thread-safe
- The NSRunLoop family of functions is not thread-safe
Start the RunLoop
Start RunLoop using the CFRunLoopRun series of functions. You can specify a timeout when starting RunLoop. There must be at least one Timer/Observer/Source inside the RunLoop before it starts. You can add a one-time Timer to the RunLoop and then call CFRunLoopRun.
Exit the RunLoop
- Specify a timeout when starting RunLoop
- Exit by CFRunLoopStop
Q: How do you implement a resident thread?
- Start one for the current thread
RunLoop
. - To the
RunLoop
Add aPort/Source
Such as maintainingRunLoop
Event loop. - Start the
RunLoop
.
Q: How to ensure that the child thread data comes back to update the UI without breaking the user’s sliding operation?
- the
The child thread
Thrown back toThe main thread
updateUI
The logic is wrapped up and submitted to the main threadkCFRunLoopDefaultMode
Under. - Current user slide
tableView
In aUITrackingRunLoopMode
This logic is not executed in mode. - When the user stops sliding, the current thread
mode
Switch to thekCFRunLoopDefaultMode
Under, updates are processedUI
The logic.
RunLoop application
What Apple does with RunLoop
RunLoop is used in AutoreleasePool, event response, gesture recognition, interface updates, timers, PerformSelecter, GCD, network request base, and more
Fixed NSTimer events not executing when scrolling through lists
- As I slide,
currentMode
fromkCFRunLoopDefaultMode
Switch to theUITrackingRunLoopMode
. - Can be achieved by
CFRunLoopAddTimer(runLoop,timer,commonMode)
Function,timer
Added to thecommonMode
In the middle. commonMode
The sync function synchronizes one event source to multiple eventsmode
In the middle.
Automatic release pool creation and release times in Runloop
– The system creates an Autoreleaspool when Runloop starts processing an event.
- Autoreleaspool is released after an event is processed.
- Autoreleasepool, which we created manually, does the drain operation after the block completes. Note that: When a block ends with an exception, the pool is not drained. The drain operation of the pool reduces the reference count of all objects marked autoRelease by one, but it does not mean that the object is necessarily released. We can manually retain an object in the AutoRelease Pool to extend its life (in MRC). Create and release automatic release pools using _objc_autoreleasePoolPush and _objc_autoreleasePoolPop. The underlying implementation is AutoreleasePoolPage.
- Autorelease pooling is implemented by Autorelease EpoolPage as a two-way linked list
- When an object calls the AutoRelease method, it is added to the stack of AutoreleasePoolPage
- Calling AutoreleasePoolPage:: POP sends a release message to an object on the stack. See this article for more information on how AutoreleasePoolPage works
Monitor the caton
You can monitor the lag by monitoring the event interval of the Runloop’s kCFRunLoopBeforeSources and kCFRunLoopAfterWaiting.
Create child threads to execute tasks
You can create a thread, and then in other threads through the performSelector: onThread: withObject: waitUntilDone: routed to the child thread for processing.
AsyncDisplayKit
AsyncDisplayKit(now Texture) is Facebook’s open-source framework for asynchronously drawing UIs. ASDK implements a similar interface update mechanism modeled after the QuartzCore/UIKit framework: Add an Observer to the RunLoop of the main thread, listen for kCFRunLoopBeforeWaiting and kCFRunLoopExit events, and, upon receiving a callback, iterate over all previously queued tasks and execute them.