In this tutorial, we take a close look at one of the key methods of the UIApplicationDelegate protocol, application(_:didFinishLaunchingWithOptions:). As the name suggests, this method is called when your app finish launching. It is an ideal moment to set up your app and prepare it for the user.

Application Did Finish Launching with Options

The UIApplication singleton has a delegate that conforms to the UIApplicationDelegate protocol. When your app finished launching, the delegate object is notified through the application(_:didFinishLaunchingWithOptions:) method. Fire up Xcode and create a new project by choosing the App template from the iOS > Application section.

Application Did Finish Launching with Options

Name your project and set Interface to Storyboard. This is important. I show you how to use the UIApplicationDelegate protocol in a SwiftUI app later in this tutorial.

Application Did Finish Launching with Options

Open AppDelegate.swift. AppDelegate is a class that inherits from UIResponder and conforms to the UIApplicationDelegate protocol. The first method of the AppDelegate class is the application(_:didFinishLaunchingWithOptions:) method. This method defines two parameters, the UIApplication instance that sent the message to the app delegate and a dictionary of options. Note that the method returns a Bool. I talk more about that later in this tutorial.

Launch Options

The dictionary of launch options defines why the app was launched. It is empty if the user tapped the app icon to launch the app. Let me give you an example. If the user taps a remote notification, then the system launches your app. The system populates the dictionary of launch options to inform your app that it was launched due to a remote notification. It is up to your app to use or not use that information.

The dictionary of launch options is also useful if your app is opened in response to the user tapping a URL. Your app can extract the URL from the dictionary of launch options and respond appropriately. That brings us to the return value of application(_:didFinishLaunchingWithOptions:).

True or False

The return type of application(_:didFinishLaunchingWithOptions:) is Bool. The app delegate uses the return value to inform the system whether it can open the URL that is included in the dictionary of launch options. It is possible that your app is launched in response to the user tapping a URL, but your app decides that it isn't able to handle the URL. In that scenario, the application(_:didFinishLaunchingWithOptions:) method should return false. By returning false, your app won't be opened.

Application Will Finish Launching with Options

There is another method of the UIApplicationDelegate protocol you need to know about, application(_:willFinishLaunchingWithOptions:). As the name suggests, this method is invoked when the app is about to finish launching. The difference is that state restoration hasn't occurred when application(_:willFinishLaunchingWithOptions:) is invoked. State restoration has completed when application(_:didFinishLaunchingWithOptions:) is invoked.

Like application(_:didFinishLaunchingWithOptions:), the return value of application(_:willFinishLaunchingWithOptions:) is Bool. Returning false means that the app isn't able to handle the URL included in the dictionary of launch options and the app won't open as a result.

SwiftUI and UIApplicationDelegateAdaptor

If you use SwiftUI for your app's user interface, then you may have noticed that your project doesn't have a file with name AppDelegate.swift. No worries, though. You can still take advantage of the UIApplicationDelegate protocol and hook into the app life cycle. Create a project in Xcode and this time we set Interface to SwiftUI.

UIApplicationDelegateAdaptor

Xcode hasn't created a type that conforms to the UIApplicationDelegate protocol, so let's take care of that first. Create a Swift file and name it AppDelegate.swift. Add an import statement for the UIKit framework. Declare a final class with name AppDelegate that inherits from NSObject. This is necessary because the UIApplicationDelegate protocol inherits from the NSObjectProtocol protocol. Conform the AppDelegate class to the UIApplicationDelegate protocol.

import UIKit

final class AppDelegate: NSObject, UIApplicationDelegate {

}

Implement the application(_:didFinishLaunchingWithOptions:) method. We add a print statement and return true in the body of the application(_:didFinishLaunchingWithOptions:) method.

import UIKit

final class AppDelegate: NSObject, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("APPLICATION DID FINISH LAUNCHING")
        return true
    }

}

Creating the AppDelegate class is the first step. Open NotesApp.swift. The file in your project may be named differently but it should end in App.swift. It defines a struct that conforms to the App protocol.

We declare a private, variable property with name appDelegate of type AppDelegate. How does SwiftUI know that it should set the AppDelegate instance as the delegate of the UIApplication singleton? We do that by prefixing the declaration of the appDelegate property with the UIApplicationDelegateAdaptor property wrapper. SwiftUI takes care of the rest. It instantiates the AppDelegate instance and sets it as the delegate of the UIApplication singleton.

import SwiftUI

@main
struct NotesApp: App {

    // MARK: - Properties

    @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate

    // MARK: - App

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }

}

Let's give it a try. Build and run the app in the simulator. You should see the output of the print statement we added to the application(_:didFinishLaunchingWithOptions:) method in the console.

APPLICATION DID FINISH LAUNCHING

Keep It Simple and Fast

The methods of the UIApplicationDelegate protocol are executed on the main thread, so it is crucial that you keep these methods simple and lightweight. If it takes too long for your app to launch, the system will simply terminate your app. That is something you need to avoid at all cost. It is fine to defer some work to a later point in time, after your app has launched. Nobody likes apps that take forever to launch. Right?