Skip to main content

iOS - Continuity Lifecycle Module

Overview

Use ContinuityLifecycleModule when your module needs to handle module-owned deep links from custom URL schemes or Universal Links.

This is the iOS module hook for links that should be inspected and handled by your module. The closest Android equivalent is LifecycleModule, which receives new intents and lets a module decide whether to handle them.

For built-in FI app deeplink contracts, see Deep Linking.

When To Use ContinuityLifecycleModule

Use ContinuityLifecycleModule when:

  • your module owns the incoming link format
  • your module needs to inspect the link directly
  • the link should trigger module-specific behavior instead of built-in FI app routing
  • your module needs to respond to either custom URL schemes or Universal Links

When Not To Use It

Do not use ContinuityLifecycleModule when:

  • the link should route into an existing FI app screen or UUX route
  • the built-in FI app deeplink contract is sufficient
  • your module does not own the incoming link format

Built-in FI app deep links get the first chance to handle the link. Your module only receives the link when built-in handling does not consume it.

Supported Entry Points

ContinuityLifecycleModule can receive:

  • application(_:shouldOpenURL:withOptions:) Handles custom URL scheme deep links.
  • application(_:willContinueUserActivityWithType:) Optional preflight hook before continuing a user activity.
  • application(_:continue:restorationHandler:) Handles Universal Links.
  • application(_:didFailToContinueUserActivityWithType:error:) Handles failures for continued user activities.
  • application(_:handleEventsForBackgroundURLSession:completionHandler:) Handles background URL session continuation callbacks.

For callback methods that return Bool?:

  • true means the module handled the event
  • false means the module did not handle the event
  • nil means no module decision, so Q2MobileApp can continue default handling

URL Shapes Your Module May Inspect

Your module can be triggered in two common ways:

  • Custom URL Scheme Format: urlScheme://moduleIdentifier/path Example: q2mob://com.q2.mobile.module.demo/path
  • Universal Link Format: https://{associated-domain}/...#/moduleIdentifier/path Example: https://demo.q2.com/experimental/uux.aspx#/com.q2.mobile.module.demo/path

These are module-owned link examples. They are different from the built-in FI app deeplink contract.

Implementation

Implement ContinuityLifecycleModule when your module needs to examine incoming links and return true only when it owns and handles the link.

In the following example:

  • the module accepts custom URL scheme and Universal Link targets for com.q2.mobile.module.demo/path
  • the module normalizes incoming URLs before matching
  • the module returns nil when the link is malformed or does not belong to the module
  • the module returns true when it claims the link
Sample ContinuityLifecycleModule Implementation
import Q2ModuleInterfaces
import UIKit

final class CustomContinuityLifecycleModule: ContinuityLifecycleModule {

private let moduleTarget = "com.q2.mobile.module.demo/path"

var moduleDelegate: ModuleDelegate?
var moduleDataSource: ModuleDataSource?

func application(
_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void
) {
completionHandler()
}

func application(
_ application: UIApplication,
shouldOpenURL url: URL,
withOptions options: [UIApplication.OpenURLOptionsKey: Any]
) -> Bool? {
handle(url: url)
}

func application(
_ application: UIApplication,
willContinueUserActivityWithType userActivityType: String
) -> Bool? {
false
}

func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool? {
guard let webpageURL = userActivity.webpageURL else {
return nil
}

return handle(url: webpageURL)
}

func application(
_ application: UIApplication,
didFailToContinueUserActivityWithType userActivityType: String,
error: Error
) {
// no-op
}
}

private extension CustomContinuityLifecycleModule {

func handle(url: URL) -> Bool? {
guard let target = normalizedTarget(from: url) else {
return nil
}

guard target == moduleTarget else {
return nil
}

// Process the module-owned deep link here.
return true
}

func normalizedTarget(from url: URL) -> String? {
if let fragment = url.fragment?.lowercased(), !fragment.isEmpty {
return fragment.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
}

guard let host = url.host?.lowercased() else {
return nil
}

let path = url.path
.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
.lowercased()

return path.isEmpty ? host : "\(host)/\(path)"
}
}

Handling Rules

  • built-in FI app link handling runs first
  • module continuity handling runs only if built-in handling declines the link
  • return true only when your module owns and handled the link
  • return nil when the link is malformed or clearly not for your module

Test In Q2DevApp

Custom URL Scheme

  1. Set the FI urlScheme in settings.json.
  2. Set the same value in Q2DevApp Info.plist under CFBundleURLSchemes.
  3. Run Q2DevApp.
  4. In Safari, open a link such as: q2mob://com.q2.mobile.module.demo/path
  5. Confirm your module handles the link.
  1. Configure the associated domain in Q2DevApp.entitlements.
  2. Run Q2DevApp.
  3. In Safari, open a link such as: https://demo.q2.com/experimental/uux.aspx#/com.q2.mobile.module.demo/path
  4. Confirm your module handles the link.

Troubleshooting

  • If your module never receives the link, confirm the link is not being consumed by the built-in FI app deeplink contract.
  • If custom URL scheme handling does not fire, confirm the FI urlScheme matches the value in Q2DevApp Info.plist.
  • If Universal Link handling does not fire, confirm Associated Domains, provisioning, and Apple App Site Association configuration for the exact host being tested.
  • If your module receives the callback but should not claim the link, return nil or false instead of true.

DevApp Notes

Q2DevApp is the development app partners use to build and test modules locally.

Starting in Mobile SDK iOS 26.3.0, Q2DevApp is scene-based. The continuity lifecycle APIs and examples on this page remain valid, but your Q2DevApp must also include the required scene manifest and Q2DevAppSceneDelegate wiring described in Setup DevApp.