Introduction to AppDelegate Lifecycle methods and useful supporting methods
Introduction
AppDelegate
is a set of methods to manage shared behaviours for your app. I would say “The Singleton” of the application. In reality it is the central place where developers initialised the apps data structures, App Scenes / Views configured, Push Notification, Location Services configured, 3rd Party Frameworks Initialised (e.g.: Firebase
, Realm
, Facebook SDK
) etc.
But this is just a wrong setup and the way to build “MassiveAppDelegate”, by accumulating all these services in one place.
There is a way to structure it nicely and to separate every component with little magic and with help of Composite Design Pattern. This solution will be shown with the example below. Look at the MyCustomAppDelegate.swift
class as an example. It extracts and groups one kind of service in one place.
AppDelegate Lifecycle
In this section I will introduce the Lifecycle Methods, some not so known methods. I will tell you some use cases what I wish I knew before, to avoid issues with edge cases.
application (_:willFinishLaunchingWithOptions:)
Launch process has begun but the state restoration has not yet occurred but the main storyboard or nib file has been loaded.
App is Inactive
state while this is called.
Personally I did not use this method too often but see the benefit for some special cases when some external event opens the app.launchOptions
– is explained with the next method.
application (_:didFinishLaunchingWithOptions:)
This is called by the OS when the launch process is almost done, before your apps window and other UI have been presented.
This can be initiated by user tapping the app icon, but can be launched by OS by some background process also.launchOptions
– indicating the reason the app was launched (if any).
These reasons could be like Silent Push Notification if the app wakes up or over Deep-link is triggered the app etc.
The keys and the list of reasons can be found here.
The State of the app can be inactive
or background
(in case of background process).
Most use cases are to initialise the first screen or some 3rd party frameworks, initialise CoreData or any Storage.
applicationDidBecomeActive(_:)
The app moves to the active
state because it was launched by the user or the system, or because the user ignores an interruption ,like an incoming phone call or SMS message(nice flow graph is in previous part) that sends the app temporarily to the inactive
state.
In case if SceneDelegate
is available then sceneDidBecomeActive
will be called.
Use this method to restart any tasks that were paused (or not yet started) while the app was inactive. Use to restart timers, refresh app interface.
Typical use is also when the user is redirected to Settings Screen to turn on e.g.: Location. When the user comes back to the app, the UI can be refreshed with new Location states over this method.
If your app uses background processing this could be a place where you can initialise your first screen. But care not to create a new view every time when the app triggers this coming back from the background.
applicationWillTerminate(_:)
Called just before the app is terminated. You can use this to free shared resources, saving user data, and invalidating timers.
For apps that support background processing, when the user quits the app then this is not called as technically the app is in background.
applicationWillResignActive(_:)
The app is about to become inactive. The app moves to the inactive state because of temporary interruptions like an incoming phone call or SMS message, or when the user quits the app and it begins the transition to the background state. An app in the inactive state continues to run but doesn’t dispatch incoming events to responders.
Use it to save the partially filled forms, save user data, blur sensitive preview, pause download or cancel API calls etc.
In case if SceneDelegate
is available then sceneWillResignActive
will be called.
applicationDidEnterBackground(_:)
Called when the app is entered to the background. Use this to disable updates to your apps user interface.
In case if SceneDelegate
is available then sceneDidEnterBackground
will be called.
applicationWillEnterForeground(_:)
Called when the application moves from background to active state.
In case if SceneDelegate
is available then sceneWillEnterForeground
will be called.

All these methods have the NSNotificationCenter
option. This is useful if you want to listen to changes e.g.: from UIViewController
.
Names of notifications:
UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification
UIApplicationDidFinishLaunchingNotification
UIApplicationDidBecomeActiveNotification
UIApplicationWillResignActiveNotification
UIApplicationWillTerminateNotification
The next sections are not directly lifecycle methods but I would say the extension of lifecycle methods is some circumstances.
Push Notification
application (_:didRegisterFor RemoteNotifications WithDeviceToken)
Tells the delegate that the app successfully registered with Apple Push Notification Service (APNs). This can be called even in case of background processing. In case you want to send the new token to your server or 3rd party service, think about your use case when is the proper time to send. As this can be also triggered in case of background process.
application (_:didFailToRegister ForRemoteNotifications WithError:)
Apple Push Notification service cannot successfully complete the registration process. This is called when the app is not properly configured for remote notifications. During development, make sure your app has the proper entitlements and that its App ID is configured to support push notifications.
application (_:didReceiveRemoteNotification : fetchCompletionHandler:)
Tells the app that a remote notification arrived that indicates there is data to be fetched.userInfo
– A dictionary that contains information related to the remote notification, potentially including a badge number for the app icon, an alert sound, an alert message to display to the user, a notification identifier, and custom data.
Use this method to process incoming remote notifications for your app.
System calls this method when your app is running in the foreground or background. In addition, if you enable the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it.
Utility
application( _:open :options:)
Called to open a resource specified by a URL, and provides a dictionary of launch options. If a URL arrives while your app is suspended or running in the background, the system moves your app to the foreground prior to calling this method.
This method is not called if your implementations return false from both the application(_:willFinishLaunchingWithOptions:)
and application(_:didFinishLaunchingWithOptions:)
methods.
application( _:continue :restorationHandler:)
The app calls this method when it receives data associated with a user activity, for example, when the user transfers an activity from a different device using Handoff.
E.g.: after using Siri or Spotlight comes back to the app or using universal links.
application DidReceiveMemoryWarning(_:)
When the app receives a memory warning from the system.
application SignificantTimeChange(_:)
Examples of significant time changes include the arrival of midnight, an update of the time by a carrier, and the change to daylight savings time.
Real use case is when the user exits the airplane mode after time zone change, daily reminder with scheduled local notification or to read server time to be sure nothing is manipulated.
Security
application ProtectedData DidBecomeAvailable(_:)
Protected files are available now. Protected files are stored in an encrypted form and made available only at certain times, usually when the device is unlocked. If there is no password or any biometric protection setup then this will not be triggered. In case you are using SSL pinning for API calls, default keychain items will not be available always. E.g.: it is not available when didFinishLaunchingWithOptions
is triggered due background processing or push-notification. There is a way to allow that also but that is outside of the scope of this article.
application ProtectedData WillBecomeUnavailable(_:)
Protected files are about to become unavailable. When the device is locked or power of the button is hit and the lock is turned on.
This is useful for banking apps when you have some reference to sensitive data and want to do last minute cleanup.
Code and Examples
Below is a code example that is easy to use. I recommend playing with it. Even move the idea to your projects. Sometimes it is worth it to override a method and to do just a Print / Log. Sometimes this logs helps us to realise what is happening in the app, why is something low performance, why is there a glitch etc.
E.g.: for me logging the applicationProtectedData WillBecomeUnavailable
method helped a lot to realise that some issue was happening just for the users who had biometric security setup.

I have marked the logs with different coloured emojis to be able to easier follow the code and the log examples. This is the trick to having a colourful debug console in xcode. 😉
Legend:
🔵- AppDelegate
lifecycle methods
🟣- AppDelegate
Notification methods
🟡- AppDelegate
“action” methods, mostly by user initiated by deep-link, universal-link or url trigger.
🟠- AppDelegate
Utility methods. Basically I could not group these ones.
🔴- Example of CustomAppDelegate
and the way how to avoid MassiveAppDelegate. For every Manager, Service, 3rd party SDK etc. you can create one of these.
🟤- UIView
lifecycle method calls
🟢- UIViewController
lifecycle method calls
🔓, 🔐- Lock and Unlocked phone event
Below you can see a code example what shows the Lifecycle logs, show the solution how to resolve the “MassiveAppDelegate” issue.
Code example.
Below you can see some common cases and their test results. It show in what order will be fired the Lifecycle methods of different components. Keep in mind that this are just some use cases and there is almost infinite combination. Best would be to move the idea to your project base and play with the logs there.


You can see that after some time, Background time remaining will be triggered by the OS.
As you can see Layout Subview methods are called multiple times. And even more often when lots of subviews are added and layout.






Background Modes
If you want to enable Background Modes. You can do it by clicking on project settings and then select tab “Signing and Capabilities”. There you can click on “+” sign and Background modes.




How To Test Background Modes From Xcode
To be able to try this out on your own. You must edit the Scheme and turn on “Launch duo to a background fetch event”. How to turn it on is presented in the next pictures.


How To Test Push Notifications on Simulator
If you want to test PushNotification on a simulator. You need to check on Background Modes “Remote notification”. If you scroll a bit up, it is presented in the picture.
Next step would be to create a payload.apns
file. What contain next:
You just need to change the “Simulator Target Bundle” on line 2, to your bundle id from the project.
And the last step is to drag and drop the payload.apns
file into the simulator. At this moment Push Notification should pop-up and you can see the lifecycle. You get the idea. Now you can also play with payload and change to Silent Push Notification and see what’s happening.
Use case 👉 Solution
Similar cases like in the previous article mentioned. If you use SSL pinning with API calls. Most likely you are storing certificates in the keychain, at the most secure place. If something wakes up the application from background and you are doing some API call early with application(_:didFinishLaunchingWithOptions:)
, then it could fail as keychain is not available at that moment, mean SSL will be not available, mean back end will reject your API call (there is a way to allow keychain to be available but need custom keychain configuration, by default in this case it is not available).
Solution is the same as the previous. Move screen init to applicationDidBecomeActive(_:)
or create a temporary preloader screen. But the best would be to configure the keychain as kSecAttrAccessibleAfterFirstUnlock
.
Outro
As you can see possibilities are infinite. I can’t show you every option, but you got the idea and the “tool” how to investigate it yourself. 🙂 If you are a bit confused, as many areas are covered with this tutorial. In the future I will try to write articles for subjects like background processing, how to test it, push notifications with a simulator in a bit more detail.
In the next part I will focus to explain a bit more the meaning of UIApplication States.
If you got to this point, thanks for reading. 🙂 If you like the content please 👏, share, subscribe, buy a coffee it means to me. If you have some suggestions or questions please feel free to comment.