Contents

Responding to the launch of your app

Initialize your app’s data structures, prepare your app to run, and respond to any launch-time requests from the system.

Overview

The system launches your app when the user taps your app’s icon on the Home Screen. If your app requested specific events, the system might also launch your app in the background to handle those events.

All apps have an associated process and at least one scene, which the UIApplication and UIScene objects represent. Apps also have an app delegate object — an object that conforms to the UIApplicationDelegate protocol — which responds to important events happening within that process. Even an app that implements the scene life cycle uses an app delegate to manage fundamental events like launch and termination. At launch time, UIKit automatically creates the UIApplication object and your app delegate. It then starts your app’s main event loop before connecting to one or more of your app’s scenes.

Provide a launch storyboard

When the user first launches your app on a device, the system displays your launch storyboard until your app is ready to display its UI. Displaying the launch storyboard assures the user that your app launched and is doing something. If your app initializes itself and readies its UI quickly, the user may see your launch storyboard only briefly.

Xcode projects automatically include a default launch storyboard for you to customize, and you can add more launch storyboards as necessary. To add new launch storyboards to your project, do the following:

  1. Open your project in Xcode.

  2. Choose File > New > File.

  3. Add a Launch Screen resource to your project.

Add views to your launch storyboard and use Auto Layout constraints to size and position them so that they adapt to the underlying environment. UIKit displays exactly what you provide, using your constraints to fit your views into the available space. For design guidance, see Human Interface Guidelines.

Initialize your app’s data structures

Put your app’s launch-time initialization code in one or both of the following methods:

UIKit calls these methods at the beginning of your app’s launch cycle. Use them to:

  • Initialize data structures that your app uses across scenes.

  • Verify that your app has the resources it needs to run.

  • Perform any one-time setup when your app launches for the first time. For example, install templates or user-modifiable files in a writable directory. See Performing one-time setup for your app.

  • Connect to any critical services that your app uses. For example, connect to the Apple Push Notification service if your app supports remote notifications.

  • Check the launch options dictionary for information about why your app launched. See Determine why your app launched.

For apps that haven’t adopted the scene life cycle, UIKit loads your default user interface automatically at launch time. Use the application(_:didFinishLaunchingWithOptions:) method to make additional changes to that interface before it appears onscreen. For example, you might install a different view controller to reflect what the user was doing the last time they used the app.

Move long-running tasks off the main thread

When the user launches your app, make a good impression by launching quickly. Performing long-running tasks in application(_:didFinishLaunchingWithOptions:), application(_:willFinishLaunchingWithOptions:), or scene(_:willConnectTo:options:) might make your app appear sluggish to the user. Returning quickly is also important when launching to the background because the system limits your app’s background execution time.

Move tasks that aren’t critical to your app’s initialization out of the launch-time sequence. For example:

  • Defer the initialization of features that your app doesn’t need immediately.

  • Move important, long-running tasks off your app’s main thread. For example, run them asynchronously on a global dispatch queue or in a Task.

Determine why your scene connected

When UIKit connects to a scene in your app, it passes along a UIScene.ConnectionOptions object that contains information about why UIKit connected to the scene. For example, this could indicate that the user requested your app to open a URL, which you might use to display a screen related to information provided in the URL.

The following code shows how you can check for a URL that contains information in query items in the scene’s connection options:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        // Confirm the scene is a window scene in iOS or iPadOS. 
        guard let _ = (scene as? UIWindowScene) else { return }
        
        // Check if the scene connection options include a URL,
        // and whether the URL has query items.
        guard let linkedUrl = connectionOptions.urlContexts.first?.url,
              let linkedComponents = URLComponents(url: linkedUrl, resolvingAgainstBaseURL: false),
              let queryItems = linkedComponents.queryItems,
              !queryItems.isEmpty else {
            return
        }
        
        // Check and handle the URL and query items here.
    }
    // Other methods…
}

Determine why your app launched

When UIKit launches your app, it calls the application(_:willFinishLaunchingWithOptions:) and application(_:didFinishLaunchingWithOptions:) methods to indicate when it’s reached these points in your app’s launch process. If your app hasn’t implemented the scene life cycle, UIKit passes along a launch options dictionary to these methods with information about why your app launched. The keys in that dictionary indicate important tasks to perform immediately. For example, they might reflect actions that the user started elsewhere and wants to continue in your app. Always check the contents of the launch options dictionary for keys that you expect, and respond appropriately to their presence.

The following code shows the app delegate method for an app that handles receiving a URL. The code checks the launch options for an incoming URL, and whether that URL contains query items that you can use to configure your app. If not, the code returns false to indicate that your app can’t handle the launch options.

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Check if the launch options include a URL,
        // and whether the URL has query items.
        guard let linkedUrl = launchOptions?[.url] as? URL,
              let linkedComponents = URLComponents(url: linkedUrl, resolvingAgainstBaseURL: false),
              let queryItems = linkedComponents.queryItems,
              !queryItems.isEmpty else {
            return false
        }
        
        // Check whether your app can handle the URL and query
        // items here. Then return `true` if so, otherwise `false`.
        // ...
        
        return true
    }
    // Other methods…
}

The system doesn’t include a key unless your app supports the corresponding feature. For example, the system doesn’t include the remoteNotification key for an app that doesn’t support remote notifications.

For a list of launch option keys and information about how to handle them, see UIApplication.LaunchOptionsKey.

Topics

Launch time

See Also

Life cycle