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?

  • UIApplicationMainTo 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?

  • commonModeNot one that actually existsMode.
  • Are synchronousSource/Timer/ObserverTo multipleModeA technical solution in.

ModeItem

  • Source0
    • When adding events toSource0Instead 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.
  • 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, andNSTimerIt’s convertible.
  • CFRunLoopObserver
    • Observation time point
      • kCFRunLoopEntryComing to Loop
      • kCFRunLoopBeforeTimersAbout to process the Timer
      • kCFRunLoopBeforeSourcesAbout to process Source
      • kCFRunLoopBeforeWaiting(User-mode and kernel-mode)
      • kCFRunLoopAfterWaiting(Kernel mode to user mode)
      • KCFRunLoopExit is about to exit

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 threadRunLoop.
  • To theRunLoopAdd aPort/SourceSuch as maintainingRunLoopEvent loop.
  • Start theRunLoop.

Q: How to ensure that the child thread data comes back to update the UI without breaking the user’s sliding operation?

  • theThe child threadThrown back toThe main threadupdateUIThe logic is wrapped up and submitted to the main threadkCFRunLoopDefaultModeUnder.
  • Current user slidetableViewIn aUITrackingRunLoopModeThis logic is not executed in mode.
  • When the user stops sliding, the current threadmodeSwitch to thekCFRunLoopDefaultModeUnder, updates are processedUIThe 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,currentModefromkCFRunLoopDefaultModeSwitch to theUITrackingRunLoopMode.
  • Can be achieved byCFRunLoopAddTimer(runLoop,timer,commonMode)Function,timerAdded to thecommonModeIn the middle.
  • commonModeThe sync function synchronizes one event source to multiple eventsmodeIn 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.