Understanding iOS RunLoop: Concepts, Functions, and Practical Applications
This article explains the iOS RunLoop mechanism, its role in keeping apps responsive, how it interacts with UIApplicationMain, timers, thread management, and various RunLoop modes, and provides practical examples for using RunLoop to maintain thread life cycles and improve UI performance.
Every iOS app relies on a RunLoop to stay alive and respond to user interactions; without it, an app would become idle after launch. The RunLoop is a low‑level event‑processing loop that continuously waits for input sources, timers, and observers.
The entry point of an iOS program is int UIApplicationMain(int argc, char * _Nullable *argv, NSString *principalClassName, NSString *delegateClassName); , which creates the application object, its delegate, and sets up the main thread’s RunLoop, ensuring the app never exits.
RunLoop’s primary responsibilities are to keep the thread alive and to monitor all events such as clock events, selector events, and touch events. It processes events in different modes; the most common are NSDefaultRunLoopMode , UITrackingRunLoopMode , and NSRunLoopCommonModes . When a timer is added to a RunLoop in the default mode, it will not fire while the UI is being scrolled because the RunLoop switches to UITrackingRunLoopMode . Using NSRunLoopCommonModes makes the timer fire in both modes.
Timers can be created with two APIs:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
and
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
The first requires manually adding the timer to a RunLoop via addTimer:forMode: , while the second automatically schedules the timer on the current RunLoop.
RunLoop objects cannot be instantiated directly; they are obtained through:
CFRunLoopGetCurrent(); and CFRunLoopGetMain(); for Core Foundation, or [NSRunLoop currentRunLoop]; and [NSRunLoop mainRunLoop]; for Foundation.
Core Foundation defines five related classes: CFRunLoopRef , CFRunLoopModeRef , CFRunLoopSourceRef , CFRunLoopObserverRef , and CFRunLoopTimerRef . A RunLoop contains multiple modes, each composed of sources (event inputs), timers, and observers.
Sources represent all event origins; they can be port‑based, custom, or Cocoa selector sources. Timers correspond to NSTimer objects, and observers monitor RunLoop state changes such as kCFRunLoopBeforeSources or kCFRunLoopAfterWaiting .
Each thread has a unique RunLoop. The main thread’s RunLoop is created by the system, while a child thread’s RunLoop is created on first access and must be kept alive manually. By adding an NSTimer to a background thread’s RunLoop and running the loop, the thread remains active and can process periodic tasks.
RunLoop can also be used to off‑load heavy operations from the main thread. By adding a CFRunLoopObserverRef that executes a single time‑consuming task each loop iteration, UI lag is reduced.
In summary, RunLoop is essential for keeping iOS apps responsive, managing timers, handling multiple event modes, and preserving thread life cycles, making it a powerful tool for performance optimization.
JD Retail Technology
Official platform of JD Retail Technology, delivering insightful R&D news and a deep look into the lives and work of technologists.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.