Your app launches slowly. How do you find out why and what do you cut?
Predict first
Which change gives the biggest pre-main launch saving in an app with 40 small dynamic frameworks?
// A: merging them or linking statically
// B: adding more print logging
// C: making didFinishLaunching async
- A
- B
- C
Mental model. Getting out of the house in the morning: cut the steps that are not needed to leave, and do the rest (checking the post) after you are on your way.
Measure first, on a real device, in a Release configuration. Instruments’ App Launch template splits the timeline into system work, dyld, static initialisers and your code up to the first frame; MetricKit and Xcode Organizer report launch time from real users, which is what matters. Apple’s guidance is to reach the first frame in well under half a second, and to measure to the first usable frame rather than to didFinishLaunching. Remember prewarming: pre-main numbers from the field depend on whether the system warmed the app.
Then cut in order of size. Pre-main: reduce the number of dynamic frameworks (merge or link statically), remove +load and heavy static initialisers, trim unused code and Objective-C categories. Post-main: do only what the first screen needs. Defer everything else (analytics SDKs, feature flags, cache warming) until after the first frame, move disk and network work off the main thread, make singletons lazy, and avoid building a large view hierarchy upfront. Keep a launch budget in CI so a regression is caught the day it lands, and treat third-party SDK initialisation as part of your budget: it often dominates.
Mapping and fixing up 40 images dominates dyld’s work. Reducing the count removes it. didFinishLaunching is post-main work.
Common traps
- Initialising every SDK in
didFinishLaunching. Many can start lazily or after the first frame. - Tuning on a simulator or a debug build. It has different linking and no prewarming, so the numbers mislead.
They might follow up with
- What is a “launch budget”? A target time for each phase that CI checks, so slow additions are caught.
- What does Xcode’s “mergeable library” setting trade? Release builds merge the frameworks’ code for faster launch, while Debug keeps them separate for faster builds.
Related questions
- 6.4.1 Walk through what happens from tapping the icon to the first frame.
- 6.4.2 What does dyld do, and how do static and dynamic linking change launch?
- 6.3.1 What is a run loop, and what happens in one iteration?
← What does dyld do, and how do static and dynamic linking change…