Eine iOS-App, die in unter 2 Sekunden startet, erfordert drei gezielte Maßnahmen: die Pre-main-Phase durch statisches Linking und weniger Frameworks verkürzen, den Haupt-Thread nach main() von synchronem I/O und schweren Initialisierungen befreien und die Startzeit mit dem App Launch Instrument in Xcode messen. Wer diese drei Hebel konsequent anwendet, kann die Ladezeit in vielen Projekten um 50 bis 60 Prozent reduzieren.
Key Takeaways
- Apple empfiehlt eine Kaltstart-Zeit von unter 400 Millisekunden für die Pre-main-Phase und insgesamt unter 2 Sekunden bis zum ersten interaktiven Frame.
- Kaltstarts (Cold Launch) sind deutlich langsamer als Warmstarts (Warm Launch), weil das System die App komplett neu in den Speicher laden muss.
- Das App Launch Instrument in Xcode ist das wichtigste Werkzeug, um Engpässe im Startpfad zu finden.
- Statisches Linking ist schneller als dynamisches Linking, weil der Dynamic Linker (dyld) weniger Arbeit vor
main()leisten muss. - Lazy Loading von Frameworks und Modulen verschiebt Ladekosten auf den Zeitpunkt, an dem sie tatsächlich benötigt werden.
- App Thinning (Slicing, Bitcode, On-Demand Resources) reduziert die Binärgröße und damit indirekt die Startzeit.
- Synchrones I/O, Netzwerkanfragen und schwere Datenbank-Initialisierungen im
applicationDidFinishLaunching-Callback sind die häufigsten Ursachen für langsame Starts. - Der Launch Screen sollte statisch und einfach sein und dem ersten echten Screen so ähnlich wie möglich sehen.
os_signpostermöglicht präzise Zeitstempel im eigenen Code, die direkt in Instruments sichtbar sind.- Das iOS-Betriebssystem selbst beeinflusst die Startzeit: neuere iOS-Versionen enthalten oft Optimierungen im dyld-Linker.
Was zählt als App-Startzeit auf iOS?
Die App-Startzeit auf iOS umfasst die gesamte Zeitspanne vom Antippen des App-Icons bis zum Moment, an dem der erste interaktive Frame auf dem Bildschirm erscheint. Apple unterteilt diese Zeitspanne in zwei Phasen: die Pre-main-Phase (bevor der eigene Code in main() ausgeführt wird) und die Post-main-Phase (von main() bis zum ersten gerenderten Frame).
Die Pre-main-Phase beinhaltet das Laden von Frameworks durch den Dynamic Linker (dyld), das Ausführen von Objective-C-Klassen-Initialisierern und das Einlesen von Bibliotheken. Die Post-main-Phase umfasst UIApplicationMain(), den AppDelegate, SceneDelegate und das Laden der ersten View-Controller.
Wichtig: Nur die Zeit bis zum ersten interaktiven Frame zählt. Hintergrundprozesse, die danach starten, beeinflussen die wahrgenommene Startzeit nicht.
Was ist eine gute App-Startzeit für iOS, und kann man unter 2 Sekunden kommen?
Eine gute Startzeit liegt laut Apples Empfehlungen bei unter 2 Sekunden für den Kaltstart. Für die Pre-main-Phase gilt ein Budget von etwa 400 Millisekunden als Richtwert. Apps, die diesen Wert überschreiten, riskieren, dass das System den Startvorgang abbricht.
Unter 2 Sekunden zu kommen ist für die meisten Apps erreichbar, wenn der Startpfad systematisch analysiert und bereinigt wird. Fokussierte Refactoring-Projekte zeigen regelmäßig Verbesserungen von 50 bis 60 Prozent, ohne dass grundlegende Architekturänderungen nötig sind.
Faustregel: Je weniger Arbeit die App beim Start erledigt, desto schneller startet sie. Alles, was nicht für den ersten Screen benötigt wird, gehört nicht in den Startpfad.
Kaltstart vs. Warmstart auf iOS: Was ist der Unterschied?

Ein Kaltstart (Cold Launch) findet statt, wenn die App nicht im Speicher liegt, zum Beispiel nach einem Neustart des Geräts oder nachdem das System die App aus dem Speicher entfernt hat. Das System muss die gesamte Binärdatei laden, dyld ausführen und alle Initializer starten. Ein Warmstart (Warm Launch) hingegen findet statt, wenn die App bereits im Speicher liegt, aber nicht im Vordergrund ist. Dabei entfällt ein Großteil der Ladearbeit.
| Starttyp | Speicherstatus | Typische Dauer | Hauptkostenfaktor |
|---|---|---|---|
| Kaltstart | Nicht im Speicher | Längste Dauer | dyld, Initializer, I/O |
| Warmstart | Im Speicher (Hintergrund) | Deutlich kürzer | Post-main-Initialisierung |
| Resume | Im Vordergrund pausiert | Nahezu null | Keiner |
Für Optimierungszwecke immer den Kaltstart messen. Warmstarts verbergen echte Probleme, weil ein Großteil der Arbeit bereits erledigt ist.
Warum startet meine iOS-App so langsam?
Langsame iOS-App-Starts haben meist eine von vier Ursachen: zu viele dynamische Frameworks, schwere Initializer in der Pre-main-Phase, blockierendes I/O im Haupt-Thread oder unnötige Arbeit in applicationDidFinishLaunching.
Die häufigsten Fehler im Detail:
- Zu viele dynamische Frameworks (dylibs): Jede zusätzliche dylib erhöht die Pre-main-Zeit messbar. Apple empfiehlt, die Anzahl eigener dynamischer Frameworks auf ein Minimum zu reduzieren.
- Schwere
+initialize– oder+load-Methoden: Diese werden von der Objective-C-Runtime vormain()ausgeführt und blockieren den Start. - Synchrones I/O im Haupt-Thread: Datenbankzugriffe, das Lesen von Konfigurationsdateien oder das Schreiben von Logs beim Start blockieren den Haupt-Thread direkt.
- Netzwerkanfragen beim Start: Authentifizierung, Feature-Flags oder Analytics, die synchron beim Start abgefragt werden, können den Start um Hunderte von Millisekunden verzögern.
- Unnötige Drittanbieter-SDKs: Jedes SDK, das in
applicationDidFinishLaunchinginitialisiert wird, addiert seine eigene Startzeit.
Diagnose-Tipp: Wenn die Pre-main-Zeit über 400 ms liegt, liegt das Problem fast immer an zu vielen dylibs oder schweren Initializern.
Wie misst man die iOS App-Startzeit richtig?

Das App Launch Instrument in Xcode ist der direkteste Weg, um die Startzeit einer iOS-App zu messen und Engpässe zu finden. Es zeigt die Pre-main- und Post-main-Phasen getrennt an und liefert einen Flamegraph, der genau zeigt, welche Funktionen wie viel Zeit kosten.
Schritt-für-Schritt-Messworkflow:
- Xcode öffnen und das Projekt auf einem echten Gerät (kein Simulator) ausführen.
- Instruments starten (Product > Profile) und das App Launch Template auswählen.
- Die App starten und den Trace aufzeichnen.
- Im Flamegraph die Pre-main-Phase analysieren: Welche Frameworks laden am längsten?
- Den Time Profiler für die Post-main-Phase nutzen: Welche Methoden blockieren den Haupt-Thread?
os_signpost-Markierungen im eigenen Code setzen, um spezifische Initialisierungsabschnitte zu messen.
Wichtig: Immer auf einem echten Gerät messen, nicht im Simulator. Der Simulator nutzt den Mac-Prozessor und spiegelt das Verhalten auf einem iPhone nicht korrekt wider. Außerdem immer im Release-Build messen, da Debug-Builds deutlich langsamer sind.
Statische vs. dynamische Frameworks: Was ist schneller beim Start?
Statische Frameworks sind beim App-Start schneller als dynamische Frameworks. Der Grund: Statisch gelinkte Bibliotheken werden direkt in die App-Binärdatei eingebunden. Der Dynamic Linker (dyld) muss sie nicht zur Laufzeit laden, suchen und binden. Jede dynamische Bibliothek (dylib) fügt zur Pre-main-Zeit hinzu.
Apple empfiehlt, die Anzahl eigener dynamischer Frameworks auf unter sechs zu halten. Systemframeworks (UIKit, Foundation usw.) sind bereits gecacht und zählen nicht in gleichem Maße.
Entscheidungsregel:
- Eigene Module, die immer beim Start geladen werden: statisch linken.
- Funktionalität, die selten oder gar nicht beim Start benötigt wird: als dynamisches Framework mit Lazy Loading behandeln oder in ein On-Demand-Modul auslagern.
Wie funktioniert Lazy Loading von Frameworks in iOS-Apps?
Lazy Loading bedeutet, dass ein Framework oder Modul erst dann geladen wird, wenn es tatsächlich benötigt wird, nicht beim App-Start. Das verschiebt die Ladekosten vom Startpfad in den späteren Nutzungsfluss.
In der Praxis gibt es zwei Ansätze:
- Dlopen / NSBundle: Ein Framework wird programmatisch erst beim ersten Aufruf geladen. Das ist für Plug-in-Architekturen geeignet, aber komplex in der Handhabung.
- On-Demand Resources und separate Targets: Funktionalität, die nur in bestimmten Szenarien benötigt wird (zum Beispiel ein Scanner-Modul), wird in ein separates Framework ausgelagert und erst beim ersten Aufruf initialisiert.
Praktisches Beispiel: Ein Analytics-SDK, das nur nach dem ersten User-Interaction-Event initialisiert werden muss, sollte nicht in applicationDidFinishLaunching gestartet werden. Stattdessen kann die Initialisierung in einen Background-Thread nach dem ersten Frame verschoben werden.
Hilft App Thinning beim schnelleren Start?

App Thinning reduziert die Größe der installierten App-Binärdatei, was sich positiv auf die Startzeit auswirkt, weil weniger Daten vom Speicher in den RAM geladen werden müssen. App Thinning umfasst drei Mechanismen: App Slicing (nur die für das Gerät relevante Architektur und Assets werden geliefert), Bitcode (ermöglicht Apple, die Binärdatei nachträglich zu optimieren) und On-Demand Resources (Assets werden erst bei Bedarf heruntergeladen).
Der Effekt auf die Startzeit ist indirekt, aber messbar, besonders auf älteren Geräten mit langsamem Speicher. Eine kleinere Binärdatei bedeutet weniger I/O beim Laden.
Zusätzliche Maßnahme: Asset Catalogs konsequent nutzen und nicht benötigte Assets aus dem App Bundle entfernen. Jedes Megabyte, das nicht geladen werden muss, spart Zeit.
Best Practices: iOS-App-Startzeit unter 2 Sekunden optimieren
Diese Maßnahmen lassen sich direkt in einem bestehenden Projekt umsetzen, ohne die Architektur grundlegend zu ändern:
Pre-main-Phase:
- Anzahl eigener dynamischer Frameworks auf unter sechs reduzieren.
+load-Methoden in Objective-C entfernen oder in+initializeumwandeln.- Swift-Initializer, die globale Zustände setzen, auf Lazy Properties umstellen.
Post-main-Phase:
applicationDidFinishLaunchingauf das absolute Minimum reduzieren: nur initialisieren, was für den ersten Screen nötig ist.- Alle anderen SDK-Initialisierungen in einen Background-Thread nach dem ersten Frame verschieben.
- Synchrones I/O (CoreData-Stack, UserDefaults-Migration, Dateilesen) asynchron ausführen.
Launch Screen:
- Den Launch Screen als statisches Storyboard oder LaunchScreen.storyboard halten.
- Keine Animationen oder komplexen Views im Launch Screen verwenden.
- Den Launch Screen so gestalten, dass er dem ersten echten Screen ähnelt, um den wahrgenommenen Start zu verkürzen.
Allgemein:
- Regelmäßig mit dem App Launch Instrument messen, besonders nach dem Hinzufügen neuer Abhängigkeiten.
- Drittanbieter-SDKs auf ihre Startzeit-Auswirkungen prüfen, bevor sie integriert werden.
Beeinflusst die iOS-Version die App-Startzeit?
Ja, neuere iOS-Versionen enthalten oft Verbesserungen im dyld-Linker und im App-Launch-Pfad, die sich positiv auf die Startzeit auswirken. Apple hat in iOS-Updates wiederholt den Linking-Prozess beschleunigt und das Caching von Shared Libraries verbessert.
Für Entwickler bedeutet das: Eine App, die auf iOS 16 langsam startet, kann auf iOS 17 oder 18 bereits schneller sein, ohne Codeänderungen. Gleichzeitig können neue iOS-Versionen neue Frameworks mitbringen, die beim Start geladen werden, wenn die App sie einbindet.
Empfehlung: Die Startzeit nach jedem Major-iOS-Update neu messen und dokumentieren. So lassen sich Regressionen früh erkennen.
Häufige Fehler, die den iOS-App-Start verlangsamen
Diese Fehler sind in vielen Projekten zu finden und lassen sich oft in wenigen Stunden beheben:
- Alle SDKs in
applicationDidFinishLaunchinginitialisieren, auch wenn sie erst Minuten später benötigt werden. - Einen animierten oder komplexen Launch Screen verwenden, der das System zwingt, mehr Arbeit vor dem ersten Frame zu leisten.
- CoreData oder Realm synchron im Haupt-Thread initialisieren, bevor der erste Frame gerendert ist.
- Feature-Flag-Abfragen über das Netzwerk beim Start blockieren lassen, anstatt gecachte Werte zu nutzen.
- Zu viele Swift-Pakete als dynamische Frameworks einbinden, ohne zu prüfen, ob statisches Linking möglich ist.
Fazit
iOS-App-Startzeit unter 2 Sekunden optimieren ist kein einmaliges Projekt, sondern ein fortlaufender Prozess. Der effektivste Einstieg ist immer die Messung: App Launch Instrument starten, Kaltstart aufzeichnen, Pre-main- und Post-main-Zeiten getrennt analysieren. Dann die größten Kostentreiber identifizieren, meistens zu viele dynamische Frameworks oder blockierendes I/O im Haupt-Thread, und gezielt beheben.
Konkrete nächste Schritte:
- App Launch Instrument auf einem echten Gerät im Release-Build ausführen und die aktuelle Kaltstart-Zeit dokumentieren.
- Die Pre-main-Zeit prüfen: Liegt sie über 400 ms, die Anzahl der dynamischen Frameworks reduzieren.
applicationDidFinishLaunchingdurchgehen und alle Initialisierungen identifizieren, die nicht für den ersten Screen nötig sind.- Diese Initialisierungen in Background-Threads nach dem ersten Frame verschieben.
- Nach jeder Änderung neu messen und die Verbesserung dokumentieren.
Wer diese fünf Schritte konsequent durchführt, wird in den meisten Projekten die 2-Sekunden-Marke unterschreiten.
FAQ
Was ist der Unterschied zwischen Pre-main- und Post-main-Zeit bei iOS?
Die Pre-main-Zeit ist die Zeitspanne, bevor der eigene Code in main() ausgeführt wird. Sie umfasst das Laden von Frameworks durch dyld und das Ausführen von Initializern. Die Post-main-Zeit beginnt mit main() und endet beim ersten gerenderten Frame. Beide Phasen müssen separat optimiert werden.
Wie viele dynamische Frameworks sind für eine iOS-App akzeptabel? Apple empfiehlt, die Anzahl eigener dynamischer Frameworks auf unter sechs zu halten. Jede zusätzliche dylib erhöht die Pre-main-Zeit messbar. Systemframeworks zählen dabei nicht in gleichem Maße, da sie vom System gecacht werden.
Kann ich die Startzeit im iOS-Simulator messen? Nein, der Simulator ist für Startzeit-Messungen nicht geeignet. Er nutzt den Mac-Prozessor und spiegelt das Verhalten auf einem iPhone nicht korrekt wider. Immer auf einem echten Gerät im Release-Build messen.
Was ist os_signpost und warum ist es nützlich für die Startzeit-Optimierung?
os_signpost ist eine Apple-API, mit der Entwickler eigene Zeitstempel in den Code einfügen können. Diese Markierungen erscheinen direkt in Instruments und ermöglichen es, spezifische Initialisierungsabschnitte präzise zu messen, ohne den Code zu verändern.
Hilft es, den Launch Screen zu vereinfachen? Ja. Ein statischer, einfacher Launch Screen reduziert die Arbeit, die das System vor dem ersten Frame leisten muss. Außerdem sollte der Launch Screen dem ersten echten Screen ähneln, um den wahrgenommenen Start zu verkürzen.
Was ist App Slicing und wie hilft es beim Start? App Slicing ist ein Teil von App Thinning. Der App Store liefert nur die für das jeweilige Gerät relevante Architektur und Assets. Eine kleinere Binärdatei bedeutet weniger I/O beim Laden und damit eine kürzere Startzeit, besonders auf älteren Geräten.
Sollte ich Swift Package Manager oder CocoaPods für schnellere Starts verwenden?
Swift Package Manager unterstützt statisches Linking besser als CocoaPods in der Standardkonfiguration. Wer CocoaPods nutzt, kann mit use_frameworks! :linkage => :static statisches Linking aktivieren. Statisches Linking ist in beiden Fällen schneller als dynamisches Linking.
Wie oft sollte ich die App-Startzeit messen? Nach jeder größeren Änderung, insbesondere nach dem Hinzufügen neuer Abhängigkeiten oder SDKs, und nach jedem Major-iOS-Update. Regelmäßige Messungen helfen, Regressionen früh zu erkennen.
Was passiert, wenn meine App beim Start länger als 20 Sekunden braucht? Das System bricht den Startvorgang ab und zeigt dem Nutzer eine Fehlermeldung. Dieser Watchdog-Timer gilt als hartes Limit. In der Praxis sollte die Startzeit weit darunter liegen.
Kann Lazy Loading die Nutzererfahrung nach dem Start verschlechtern? Wenn Lazy Loading schlecht umgesetzt wird, kann es zu kurzen Verzögerungen führen, wenn ein Modul zum ersten Mal geladen wird. Die Lösung ist, das Laden im Hintergrund vorzubereiten, bevor der Nutzer die entsprechende Funktion aufruft, zum Beispiel beim ersten Scrollen oder nach einer kurzen Wartezeit nach dem Start.

Hinterlasse jetzt einen Kommentar