Skip to main content

iOS - Application Lifecycle Module

note

To receive application lifecycle events, a proper implementation of the ApplicationLifecycleModule protocol is required. Q2MobileCore will interact with your module for various application lifecycle events.

The ApplicationLifecycleModule interface is used when creating a module that needs to respond to application lifecycle events. The implementation should be responsible for handling various application states including launch, foreground/background transitions, memory warnings, and termination events.

ApplicationLifecycleModule Methods

The module provides the following capabilities:

Launch Events

  • application(_:didFinishLaunchingWithOptions:) - Called when the launch process is almost done and the app is almost ready to run

Foreground/Background Events

  • applicationWillEnterForeground(_:) - Called when the app is about to enter the foreground
  • applicationDidBecomeActive(_:) - Called when the app has become active
  • applicationWillResignActive(_:) - Called when the app is about to become inactive
  • applicationDidEnterBackground(_:) - Called when the app is now in the background

System Events

  • applicationDidReceiveMemoryWarning(_:) - Called when the app receives a memory warning from the system
  • applicationWillTerminate(_:) - Called when the app is about to terminate
  • applicationSignificantTimeChange(_:) - Called when there is a significant change in the time

Protocol Definition

ApplicationLifecycleModule Protocol
/// A type that handles events related to application lifecycle.
public protocol ApplicationLifecycleModule: LifecycleModule {

/// Tells the delegate that the launch process is almost done and the app is almost ready to run.
/// - Parameters:
/// - application: The singleton app object.
/// - launchOptions: A dictionary indicating the reason the app was launched (if any). The contents of this dictionary may be empty in situations where the user launched the app directly.
/// - Returns: `false` if the app cannot handle the URL resource or continue a user activity, otherwise return `true`. The return value is ignored if the app is launched as a result of a remote notification.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool?

/// Tells the delegate that the app is about to enter the foreground.
/// - Parameter application: Your singleton app object.
func applicationWillEnterForeground(_ application: UIApplication)

/// Tells the delegate that the app has become active.
/// - Parameter application: Your singleton app object.
func applicationDidBecomeActive(_ application: UIApplication)

/// Tells the delegate that the app is about to become inactive.
/// - Parameter application: Your singleton app object.
func applicationWillResignActive(_ application: UIApplication)

/// Tells the delegate that the app is now in the background.
/// - Parameter application: Your singleton app object.
func applicationDidEnterBackground(_ application: UIApplication)

/// Tells the delegate when the app receives a memory warning from the system.
/// - Parameter application: Your singleton app object.
func applicationDidReceiveMemoryWarning(_ application: UIApplication)

/// Tells the delegate when the app is about to terminate.
/// - Parameter application: Your singleton app object.
func applicationWillTerminate(_ application: UIApplication)

/// Tells the delegate when there is a significant change in the time.
/// - Parameter application: Your singleton app object.
func applicationSignificantTimeChange(_ application: UIApplication)
}

Implementation

There are two ways to implement an ApplicationLifecycleModule depending on your needs:

If your module inherits from Q2ModuleBase, you only need to override the methods required for your specific functionality. This approach provides default implementations for all protocol methods, making your code cleaner and more focused.

ApplicationLifecycleModule Implementation with Q2ModuleBase
import Q2ModuleInterfaces

class CustomApplicationLifecycleModule: Q2ModuleBase {

override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool? {
print("CustomApplicationLifecycleModule: didFinishLaunchingWithOptions")
// Add your custom launch logic here
return nil
}

override func applicationWillEnterForeground(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillEnterForeground")
// Add your custom foreground logic here
}

override func applicationDidBecomeActive(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidBecomeActive")
// Add your custom activation logic here
}

override func applicationWillResignActive(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillResignActive")
// Add your custom deactivation logic here
}

override func applicationDidEnterBackground(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidEnterBackground")
// Add your custom background logic here
}

override func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidReceiveMemoryWarning")
// Add your custom memory warning handling here
}

override func applicationWillTerminate(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillTerminate")
// Add your custom termination logic here
}

override func applicationSignificantTimeChange(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationSignificantTimeChange")
// Add your custom time change handling here
}
}

Option 2: Raw Implementation

For full control over all protocol methods, you can implement the ApplicationLifecycleModule protocol directly by creating an NSObject class that conforms to all protocol requirements.

Raw ApplicationLifecycleModule Implementation
import Q2ModuleInterfaces

class CustomApplicationLifecycleModule: NSObject, ApplicationLifecycleModule {

var moduleDelegate: ModuleDelegate?

var moduleDataSource: ModuleDataSource?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool? {
print("CustomApplicationLifecycleModule: didFinishLaunchingWithOptions")
// Add your custom launch logic here
return nil
}

func applicationWillEnterForeground(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillEnterForeground")
// Add your custom foreground logic here
}

func applicationDidBecomeActive(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidBecomeActive")
// Add your custom activation logic here
}

func applicationWillResignActive(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillResignActive")
// Add your custom deactivation logic here
}

func applicationDidEnterBackground(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidEnterBackground")
// Add your custom background logic here
}

func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationDidReceiveMemoryWarning")
// Add your custom memory warning handling here
}

func applicationWillTerminate(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationWillTerminate")
// Add your custom termination logic here
}

func applicationSignificantTimeChange(_ application: UIApplication) {
print("CustomApplicationLifecycleModule: applicationSignificantTimeChange")
// Add your custom time change handling here
}

// MARK: - Module Protocol Requirements

func log(_ message: String, level: LogLevel) {
print("CustomApplicationLifecycleModule: \(message)")
}

func logEvent(_ name: String, attributes: [String: Any]?) {
print("CustomApplicationLifecycleModule: Event - \(name), attributes: \(attributes ?? [:])")
}

func logError(error: Error, attributes: [String: Any]?) {
print("CustomApplicationLifecycleModule: Error - \(error), attributes: \(attributes ?? [:])")
}
}

Usage Example

Here's an example of how you might use an ApplicationLifecycleModule to track user session analytics:

Session Analytics ApplicationLifecycleModule
import Q2ModuleInterfaces

class SessionAnalyticsModule: Q2ModuleBase {

private var sessionStartTime: Date?

override func applicationDidBecomeActive(_ application: UIApplication) {
sessionStartTime = Date()
logEvent("session_started", attributes: ["timestamp": sessionStartTime?.timeIntervalSince1970])
}

override func applicationWillResignActive(_ application: UIApplication) {
guard let startTime = sessionStartTime else { return }
let sessionDuration = Date().timeIntervalSince(startTime)
logEvent("session_ended", attributes: [
"duration": sessionDuration,
"timestamp": Date().timeIntervalSince1970
])
}

override func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
logEvent("memory_warning_received", attributes: ["timestamp": Date().timeIntervalSince1970])
}
}