Deep Linking Setup and Configuration

StarterAppKit comes pre-configured with deep linking capabilities. To leverage this functionality for your own app, follow the steps below.

Initial Configuration

  1. Update Constants.swift

    In your Constants.swift, locate the deepLinkConfig and update the values to match your app’s details:

static let deepLinkConfig = DeepLinkConfiguration( customURLScheme: "yourscheme", // Your custom URL scheme (e.g., "myapp") universalDomain: "yourdomain.com", // Your website domain paths: AppDeepLink.allCases, // No need to change this bundleIdentifier: "your.bundle.id" // Your app's bundle identifier )
  1. Update URL Types in info.plist

Open your info.plist file and adjust the URL types:

Update your info.plist
  • Set Item 0 to match your customURLScheme in Constants.swift.
  • Set URL identifier to match your universalDomain in Constants.swift.

Adding Custom Deep Link Paths

Adding custom deep link paths allows you to navigate users to specific content or features within your app.

Step-by-Step Instructions

  1. Define a New Path in AppDeepLink

Open your AppDeepLink enum and add a new case for your custom path. For example, products:

public enum AppDeepLink: String, DeepLinkPath, CaseIterable { case home = "home" case profile = "profile" case settings = "settings" // Add your new path here case products = "products" public var requiredParameters: Set<String> { switch self { case .resetPassword, .verifyEmail, .confirmAuth: return ["token"] // Add required parameters for your new path case .products: return ["id"] case .home, .settings, .profile: return [] } } public var requiresAuth: Bool { switch self { case .resetPassword, .verifyEmail, .confirmAuth: return false // Specify if your new path requires authentication case .products: return true case .home, .settings, .profile: return true } } }
  1. Handle the Path in Your Views In InitialView.swift, map the new path to a destination view:
@ViewBuilder private func destinationView(for path: String) -> some View { switch path { case AppDeepLink.confirmAuth.rawValue: ConfirmAuthView(vm: ConfirmAuthViewModel(token: vm.parameters["token"] ?? "")) case AppDeepLink.resetPassword.rawValue: ResetPasswordView(vm: AuthViewModel(token: vm.parameters["token"] ?? nil)) // Add your new path case here case AppDeepLink.products.rawValue: ProductView(productId: vm.parameters["id"] ?? "") default: EmptyView() } }
You only need to declare your view here if you want the deeplink to open it immediately. If you need the deeplink to navigate through another view first, continue reading.

Navigating Through Multiple Deep Link Paths

Deep links can contain multiple paths, allowing for nested navigation. For instance, a single-path deeplink like myapp://profile opens ProfileView directly, but a multi-path deeplink such as myapp://home/profile will first open the HomeView and then navigate to ProfileView.

Note: If multiple paths are present, you must handle the navigation in your code once the parent view is displayed.

Example: Handling Multi-Path Navigation

When a deeplink has multiple paths, the app needs to navigate through them in sequence. Below is an example of how to manage this scenario.

  1. Identify the Next Destination

At the top of your view, define a computed property to get the next path from the remaining paths:

var nextDestination: (path: String, remaining: [String])? { guard let paths = remainingPaths, !paths.isEmpty else { return nil } let next = (paths[0], Array(paths.dropFirst())) return next }
  1. Create a Navigation Trigger State

Add a state variable to indicate when navigation should occur:

@State private var shouldNavigate = false
  1. Trigger Navigation on Appear

When the view appears, if there is a next destination, set shouldNavigate to true:

.onAppear { if nextDestination != nil { shouldNavigate = true } } .background( Group { if let next = nextDestination { CustomNavigationLink( shouldNavigate: $shouldNavigate, destination: { switch next.path { case "profile": return AnyView( UserProfileView( vm: UserProfileViewModel(), remainingPaths: next.remaining ) ) default: return nil } }, label: { EmptyView() } ) } } )
For a complete reference on multi-path navigation and how the navigation stack is handled, see `BaseView.swift`.

Testing Your Deep Links

Testing ensures your deep links work as intended before releasing your app to users. Here are a few methods and tips for testing:

  1. Using the Simulator (Xcode)
  • Run the App: Launch your app in the iOS Simulator.
  • Open the URL: In the Simulator, go to Features > Open URL... and type in your deeplink URL (e.g., yourscheme://app/home or yourscheme://app/home/profile).
  • Verify Navigation: Confirm that your app launches and navigates to the expected screen.
  1. Using Terminal Commands (macOS) You can also trigger deeplinks using the xcrun simctl openurl command on macOS. For example:
xcrun simctl openurl booted yourscheme://app/products?id=123

This will open the currently running simulator and launch the deeplink.

  1. Universal Links Testing (iOS Devices) If you’ve set up universal links (using yourdomain.com), navigate to a URL in Safari on a device that matches your universal domain and path, such as https://yourdomain.com/products?id=123. Ensure that the app opens and navigates correctly.
  • Make sure the associated domain configuration is correct.
  • Test with a physical device if possible, since universal links often require a valid Apple App Site Association file and a published domain.
  1. Integration with Your Backend or QA Environment
  • If your deep links are generated by a backend service, test end-to-end by clicking on links provided by your QA or staging environment.
  • Confirm that all required parameters (id, token, etc.) are passed correctly and that authentication requirements are respected.
  1. Automated Testing
  • Consider writing UI tests using Xcode’s UI testing framework (XCTest) to verify deeplink navigation flows.
  • Automate the process of opening deeplinks and validating the presented view for consistency and regression prevention.
If you experience issues during testing, double-check your scheme, domain, and info.plist settings. Also, ensure that the paths and parameters match exactly what’s expected in AppDeepLink and in your `Constants.swift` configuration.