Understanding RunLoop: Overview, Principles, and Practical Usage in iOS
This article explains what a RunLoop is, why it exists, its internal structure and modes, how it interacts with threads, and common iOS development techniques such as keeping threads alive, image loading, timer handling, and performance monitoring.
RunLoop Overview – A RunLoop (or run loop) is essentially a do‑while loop that keeps a thread alive, processing events when there is work and sleeping when idle, thereby improving performance and conserving resources.
Purpose of RunLoop – It ensures continuous program execution, handles various app events (event response, gesture recognition, UI refresh, autorelease pool, NSTimer , etc.), and saves CPU cycles by sleeping when no tasks are pending.
RunLoop Implementation – iOS provides two APIs: CFRunLoop (CoreFoundation) and NSRunLoop (Foundation). NSRunLoop is a thin Objective‑C wrapper around the underlying CFRunLoop struct. CFRunLoop is thread‑safe, while NSRunLoop is not.
Core Data Structures – The CFRunLoop struct contains fields such as _currentMode , _modes , _commonModes , and _commonModeItems . Each RunLoop has one active mode at a time, while multiple modes can be defined.
RunLoop Modes – Important modes include: 1) KCFRunLoopDefaultMode – default for the main thread. 2) UITrackingRunLoopMode – used while scrolling to keep UI responsive. 3) KCFRunLoopCommonMode – a placeholder grouping default and tracking modes. 4) UIInitializationRunLoopMode – used only during app launch. 5) CSEventReceiveRunLoopMode – rarely used.
Event Sources – RunLoop processes three kinds of sources: • CFRunLoopSourceRef (Source0/Source1) – custom event sources. • CFRunLoopTimerRef – timers that fire at scheduled intervals. • CFRunLoopObserverRef – observers that monitor RunLoop state changes.
RunLoop and Threads – Each thread can have at most one RunLoop, stored in a global dictionary keyed by the thread. The RunLoop is created lazily on first access via CFRunLoopGetMain() or CFRunLoopGetCurrent() and destroyed when the thread exits. The main thread’s RunLoop is created automatically; secondary threads have none unless explicitly started.
Typical Development Uses
Keeping a thread alive: add a persistent source (e.g., a Source1) so the RunLoop never exits.
Delayed image loading in UITableView : schedule setImage: on NSDefaultRunLoopMode so it runs after scrolling finishes.
Ensuring NSTimer fires while scrolling: add the timer to NSRunLoopCommonModes so it works in both default and tracking modes.
Detecting UI stalls: create a CFRunLoopObserverRef in NSRunLoopCommonModes to watch for KCFRunLoopBeforeSources and KCFRunLoopAfterWaiting states; if the state does not change within a threshold, the app is considered blocked and a stack dump can be generated.
Code Examples
[self.img performSelector:@selector(setImage:) withObject:image afterDelay:0 inModes:[NSDefaultRunLoopMode]]; NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerEvent) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];In summary, a RunLoop is a loop that continuously checks for work, processes sources, timers, and observers, and sleeps when idle, providing a foundation for responsive iOS applications.
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.