Chapters

Hide chapters

SwiftUI Cookbook

Live Edition · iOS 16.4 · Swift 5.8.1 · Xcode 14.3.1

Understanding & Reducing Startup Time With Instruments
Written by Team Kodeco

It’s crucial to ensure that your app starts up quickly. A slow launch can frustrate users and may even lead to your app being killed by the system watchdog process. Tools such as Xcode’s Instruments can help you investigate and reduce your app’s startup time.

Let’s consider an example where we have a AnalyticsService that has a very long startup time in a SwiftUI app.

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

    AnalyticsService.shared.longStartupTime()

    return true
  }
}

class AnalyticsService {
  static let shared = AnalyticsService()
  private init() {}

  func longStartupTime() {
    sleep(10)
  }
}

struct ContentView: View {
  var body: some View {
    Text("Hello world!")
  }
}

You’ll also need to update your main app file to the following:

@main
struct SwiftUI_ToolkitApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

Note your preview shouldn’t load at the moment, as the app startup time is causing it to time out.

In the above code, AnalyticsService.shared.longStartupTime() is causing a delay in the app’s startup time due to a sleep call.

Here’s how to use Instruments to investigate:

  1. Run your app in the simulator or on a device.
  2. In Xcode, choose Profile from the Product menu or press Command-I. This will launch Instruments.
  3. In the template selection dialog that appears, choose App Launch. This will launch the Time Profiler Instrument.
  4. Click the red Record button at the top-left to start profiling your app.
  5. Once the app starts, you can stop the recording.

On the timeline, you can see the processes and how much time each task is taking. You can expand each process to see what methods are being called during startup and how long they take.

Here’s what the Time Profiler Instrument looks like:

The Time Profiler Instrument in Instruments.
The Time Profiler Instrument in Instruments.

You should notice that AnalyticsService.shared.longStartupTime() is causing a significant delay in the app’s startup time. This is a clear sign that the method needs optimization.

One possible way to improve this is by deferring the call to longStartupTime() until after the app has finished launching or performing it on a background thread. Here’s an example of how you can do this:

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
    DispatchQueue.global().async {
      AnalyticsService.shared.longStartupTime()
    }

    return true
  }
}

Here’s what your preview should look like:

The Time Profiler Instrument in Instruments after optimization.
The Time Profiler Instrument in Instruments after optimization.

In the modified code, longStartupTime() is called on a background thread, which won’t block the main thread and allows your app to start up faster.

Remember, Instruments is a powerful tool to help you diagnose and solve performance issues in your app.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.