Tap the iseeido icon and, before any of the app’s own code has run, iOS puts up a picture: the launch screen. It is a still image, named in the app’s Info.plist, and it stays until the app draws its first frame.
Until build 12, what came after it was a blank screen. Behind that blank, the app was building its two tabs, Go and Maps, and creating the first Google map was most of the work. In a Release build on the simulator, it took about 0.4 seconds.
Since build 12, a cold launch spends that wait on something to look at. An arrow searches a few streets, finds its way to a door, and steps through it.
Searching, then going
The doorway and the arrow are the app icon’s own.
- Search. Dots light up along the roads, spreading outwards from you round corners and never through a block, the way a route search spreads.
- Way found. A quarter of a second in, the search fades and the route draws itself, periwinkle on an ink casing, as on the street map.
- Travel. A small white arrow follows the route to the door, turning at each corner.
- Through the door. The arrow grows into the app’s mark as the doorway lights up yellow and the streets fade away.
The wait holds the main thread
Building the tabs runs on the app’s main thread, and while it does, nothing else on that thread gets a turn. SwiftUI steps its animations on the main thread, so a SwiftUI animation freezes through exactly the wait it was meant to cover.
So the launch animation is written in Core Animation instead. Every movement is handed over at the start, as an explicit animation with its own start time. Animations committed this way run in the render server, so they keep moving while the main thread is busy.
The order matters too. The tabs are not started until the animation’s first frame is on screen. A twentieth of a second after that frame, the app begins building them underneath it. Any sooner, and the first frame would wait for them.
The first frame is the launch screen
The still picture and the moving one are the same drawing. A small script draws the launch screen from the coordinates the animation uses: the streets, the doorway still dim, the arrow at the start. The animation then draws that picture in exactly the same place, so the image on screen simply starts to move. A recorded launch matched pixel for pixel at the handover.
About a second, on purpose
Every moment the animation runs after the tabs are ready is added to every cold launch. So its length was measured, from the tap to a usable app, in a Release build on the simulator. With no animation, that took 2.5 seconds. A version 1.4 seconds long made it 3.7. The version that shipped lasts about a second, and makes it 3.3.
- 0.4 sto build the tabs, measured on the simulator
- about 1 sthe animation, from its first frame
- 0.8 sadded to a cold launch on the simulator
If the tabs are still not ready when the arrow reaches the door, the doorway breathes, fading gently down and back up, until they are. The What’s New screen opens after the animation, not over it.
A tap skips straight to the end. With Reduce Motion on, there is no searching or travelling: the streets simply fade into the mark. The animation is hidden from VoiceOver.
The timings, in seconds
- The search spreads outwards at 900 points a second.
- The way is found at 0.25, and the route draws itself over the next 0.25.
- The arrow sets off 0.03 after the way is found, and travels for 0.42, reaching the door at 0.70.
- Stepping through the door takes 0.25, and the picture holds for 0.08 more: 1.03 in all.
- The search’s dots sit along every road, and each one lights when the search reaches it along the streets. The distances come from a shortest path search over the start, every road end and every crossing.
What it means with the phone in your hand
Opening the app no longer starts with an empty screen. The picture iOS shows before the app runs turns into the animation without a jump, and the animation keeps moving while the app gets ready. It is about a second long, and a tap ends it sooner.