How to Supercharge iOS App Startup: Practical Optimization Techniques
This article explains how to measure, analyze, and dramatically improve iOS app launch performance through profiling, removing unused code, compressing assets, and restructuring view controller loading, illustrated with a real‑world WiFi manager case study.
Introduction
This article describes how to optimize iOS app startup performance in four parts: basic concepts, defining optimization goals, a concrete case study of the WiFi Manager app, and a final summary.
Part 1 – Some Basics
1. App launch process
Parse Info.plist (splash screen, sandbox, permissions)
Mach‑O loading (select CPU slice, load dependent Mach‑O files, resolve symbols, run __attribute__((constructor)), load categories, run C++ static objects and ObjC +load)
Program execution (call main(), UIApplicationMain(), applicationWillFinishLaunching)
2. Measuring launch time
Cold launch (app killed) is the focus. Using Xcode’s DYLD_PRINT_STATISTICS environment variable (set to 1) prints a detailed timing report in the console.
Example report:
Total pre‑main time: 94.33 ms (100.0%)
dylib loading time: 61.87 ms (65.5%)
rebase/binding time: 3.09 ms (3.2%)
ObjC setup time: 10.78 ms (11.4%)
initializer time: 18.50 ms (19.6%)
slowest initializers:
libSystem.B.dylib: 3.59 ms (3.8%)
libBacktraceRecording.dylib: 3.65 ms (3.8%)
GTFreeWifi: 7.09 ms (7.5%)Interpretation:
Pre‑main takes 94.33 ms.
Dynamic library loading dominates (61.87 ms); ObjC class initialization and other initializers consume the rest.
The three longest initializers are libSystem.B.dylib, libBacktraceRecording.dylib, and GTFreeWifi.
3. Factors affecting launch time
Before main()
Number of dynamic libraries
Number of ObjC classes
Number of C constructors
Number of C++ static objects
Number of ObjC +load methods
Experiments show that more libraries or classes linearly increase launch time; reducing them yields noticeable gains.
Avoid writing C constructors, C++ static objects, and ObjC +load methods when possible; use dispatch_once() instead.
After main()
Execution of main() itself
Execution of applicationWillFinishLaunching Loading of the root view controller, its child view controllers, and their view hierarchies
4. ApplicationWillFinishLaunching timing
Typical code in AppDelegate and view controllers is shown, illustrating the order in which -viewDidLoad methods are called.
Part 2 – Defining Optimization Goals
Aim to finish all work before main() within 400 ms.
Overall launch must stay under 20 seconds, otherwise the system kills the app.
The 400 ms target aligns with the duration of the iOS launch animation.
Part 3 – WiFi Manager Startup Optimization
Result before optimization (image omitted for brevity).
1. Remove unused dynamic libraries
Manually delete unnecessary libraries and re‑add only those required.
2. Remove unused classes
Use tools like fui (Find Unused Imports) to list dead classes, then delete them after manual verification.
3. Merge similar categories
Consolidate Objective‑C categories to reduce the number of extensions loaded at startup.
4. Compress image resources
Compress PNG assets (e.g., with TinyPNG) to reduce I/O during launch.
5. Optimize applicationWillFinishLaunching
Streamline business logic, reduce concurrent HTTP requests from 66 to 23, and move non‑essential work out of the launch path.
6. Optimize rootViewController loading
Analyze the UI hierarchy (image omitted) and defer loading of heavy child view controllers or subviews.
7. Handle background cold‑start scenarios
If the app is launched in the background (e.g., from Wi‑Fi settings), skip loading the root view controller entirely.
Part 4 – Summary
Use DYLD_PRINT_STATISTICS to profile pre‑main time.
Reduce the number of dynamic libraries, ObjC classes, and categories; scan for unused code regularly.
Replace __attribute__((constructor)), C++ static objects, and ObjC +load with dispatch_once().
Compress images within designer‑acceptable limits.
Analyze applicationWillFinishLaunching with anchor points and defer non‑critical work.
Delay loading of deep view controller hierarchies when possible.
Consider not loading the root view controller for background cold‑starts.
Remember that visual perception of speed often matters more than raw metrics.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
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.
