Optimizing iOS App Launch Time

An app launch is a race against the system's watchdog timer. The OS loads your app in two phases: pre-main and main. Optimizing both is key. The biggest footgun is ignoring the pre-main phase, where bloated dynamic libraries can kill performance.
WHY IT EXISTS: Users expect apps to be instantly responsive. The operating system enforces this with a "watchdog" timer. If an app takes too long to launch and become interactive, the OS will terminate it, leading to a crash from the user's perspective. Optimizing launch time is about ensuring a fast, reliable first impression.
THE MENTAL MODEL: Think of an app launch not as a single event, but as a two-stage process. The first stage, "pre-main," is controlled by the OS. It loads your app's executable and all its dependent dynamic libraries (dylibs) into memory. The second stage, "main," is when your own code starts executing, beginning with your AppDelegate or SceneDelegate until your first UI is on screen. Your total time budget is for both stages combined.
HOW IT WORKS: The launch process is divided into pre-main and main time. Pre-main time is handled by the system's dynamic linker, dyld. It loads the app executable and all dylibs, fixes pointer locations (rebasing/binding), and runs static initializers. This phase is often a hidden performance hog. You can measure it by setting the DYLD_PRINT_STATISTICS environment variable in Xcode. Main time begins when your app's main() function is called. It includes all the work in your AppDelegate's application(_:didFinishLaunchingWithOptions:). The goal here is to get a UI on screen as fast as possible and defer all other work, like network requests or heavy database setup.
WHEN TO USE IT: Launch time optimization is a continuous process for every iOS app. It becomes critical when your app has many features and dependencies, you use a large number of third-party SDKs, or you receive user complaints about slow startup. Profile first, then optimize.
WHEN NOT TO USE IT: There is no scenario where you should ignore launch time. However, avoid premature optimization. For a simple app with few dependencies, the default launch time might already be excellent. Focus your efforts where they have the most impact based on profiling, not guesswork.
ONE CANONICAL EXAMPLE: A common bottleneck is performing a synchronous, blocking network request in application(_:didFinishLaunchingWithOptions:) to fetch configuration. This is a major anti-pattern. Instead, display a placeholder UI immediately and perform the network request asynchronously in the background. The UI can then be updated once the data arrives, providing a much better user experience and a faster initial launch.
Read the original → developer.apple.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.