Bird
Raised Fist0
iOS Swiftmobile~20 mins

Deep linking in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: DeepLinkDemo
This screen shows how to handle deep links in an iOS app. When the app opens via a URL, it displays the path and query parameters on screen.
Target UI
-------------------------
| Deep Link Demo        |
|-----------------------|
| URL Path:             |
|                       |
| Query Params:         |
|                       |
|                       |
|                       |
|                       |
-------------------------
Handle incoming URLs using SceneDelegate method
Parse URL path and query parameters
Display the path and parameters on the screen
Show a default message if app opened normally without URL
Starter Code
iOS Swift
import SwiftUI

@main
struct DeepLinkDemoApp: App {
    @StateObject var deepLinkModel = DeepLinkModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(deepLinkModel)
        }
    }
}

class DeepLinkModel: ObservableObject {
    @Published var path: String = "No URL opened"
    @Published var queryParams: String = ""
}

struct ContentView: View {
    @EnvironmentObject var deepLinkModel: DeepLinkModel

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Text("URL Path:")
                .font(.headline)
            Text(deepLinkModel.path)
                .foregroundColor(.blue)
            Text("Query Params:")
                .font(.headline)
            Text(deepLinkModel.queryParams)
                .foregroundColor(.green)
            Spacer()
        }
        .padding()
    }
}

// TODO: Add URL handling in SceneDelegate or equivalent
Task 1
Task 2
Task 3
Solution
iOS Swift
import SwiftUI

@main
struct DeepLinkDemoApp: App {
    @StateObject var deepLinkModel = DeepLinkModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(deepLinkModel)
        }
        .onOpenURL { url in
            // Parse URL path
            deepLinkModel.path = url.path.isEmpty ? "(empty path)" : url.path

            // Parse query parameters
            if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
               let queryItems = components.queryItems, !queryItems.isEmpty {
                let params = queryItems.map { "\($0.name)=\($0.value ?? "")" }.joined(separator: ", ")
                deepLinkModel.queryParams = params
            } else {
                deepLinkModel.queryParams = "No query parameters"
            }
        }
    }
}

class DeepLinkModel: ObservableObject {
    @Published var path: String = "No URL opened"
    @Published var queryParams: String = ""
}

struct ContentView: View {
    @EnvironmentObject var deepLinkModel: DeepLinkModel

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Text("URL Path:")
                .font(.headline)
            Text(deepLinkModel.path)
                .foregroundColor(.blue)
            Text("Query Params:")
                .font(.headline)
            Text(deepLinkModel.queryParams)
                .foregroundColor(.green)
            Spacer()
        }
        .padding()
    }
}

This solution uses SwiftUI's .onOpenURL modifier to handle deep links when the app opens or is already running. The URL's path and query parameters are extracted and stored in a shared DeepLinkModel observable object. The ContentView observes this model and updates the UI to show the current URL path and parameters.

This approach is simple and fits well with SwiftUI's reactive design. It avoids the older SceneDelegate method and uses modern SwiftUI lifecycle APIs.

Final Result
Completed Screen
-------------------------
| Deep Link Demo        |
|-----------------------|
| URL Path:             |
| /product/details      |
| Query Params:         |
| id=123, ref=abc       |
|                       |
|                       |
|                       |
-------------------------
When the app opens via a URL like myapp://product/details?id=123&ref=abc, the screen updates to show the path '/product/details' and query parameters 'id=123, ref=abc'.
If the app opens normally without a URL, it shows 'No URL opened' and no query parameters.
Stretch Goal
Add support to handle deep links when the app is already running in the background.
💡 Hint
Use the .onOpenURL modifier in your SwiftUI App struct to handle URLs anytime the app receives them.

Practice

(1/5)
1. What is the main purpose of deep linking in an iOS app?
easy
A. To increase app storage capacity
B. To improve app startup speed
C. To open a specific screen or content inside the app from a link
D. To change the app's icon dynamically

Solution

  1. Step 1: Understand deep linking concept

    Deep linking allows users to open a specific part of an app directly from a link, not just launch the app.
  2. Step 2: Compare options

    Options A, B, and D are unrelated to deep linking's purpose.
  3. Final Answer:

    To open a specific screen or content inside the app from a link -> Option C
  4. Quick Check:

    Deep linking = open specific app content [OK]
Hint: Deep linking = direct app content access from links [OK]
Common Mistakes:
  • Confusing deep linking with app performance improvements
  • Thinking deep linking changes app appearance
  • Mixing deep linking with app storage features
2. Which method in AppDelegate handles opening your app via a custom URL scheme?
easy
A. application(_:didFinishLaunchingWithOptions:)
B. application(_:open:options:)
C. applicationDidBecomeActive(_:)
D. applicationWillTerminate(_:)

Solution

  1. Step 1: Identify URL handling method

    The method application(_:open:options:) is called when the app is opened via a URL scheme.
  2. Step 2: Exclude other lifecycle methods

    Other methods handle app launch, active state, or termination, not URL opening.
  3. Final Answer:

    application(_:open:options:) -> Option B
  4. Quick Check:

    Custom URL open method = application(_:open:options:) [OK]
Hint: URL open handling uses application(_:open:options:) [OK]
Common Mistakes:
  • Choosing didFinishLaunchingWithOptions for URL handling
  • Confusing app lifecycle methods with URL handling
  • Ignoring the options parameter in the method
3. Given this code snippet in AppDelegate, what will happen when the app opens with URL scheme myapp://profile?id=123?
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
  if url.scheme == "myapp" && url.host == "profile" {
    print("Open profile with id: \(url.query ?? "none")")
    return true
  }
  return false
}
medium
A. Returns false without printing anything
B. Prints 'Open profile with id: none' and returns false
C. Crashes because url.query is nil
D. Prints 'Open profile with id: id=123' and returns true

Solution

  1. Step 1: Check URL scheme and host

    The URL scheme is "myapp" and host is "profile", so the if condition is true.
  2. Step 2: Evaluate url.query value

    The query part is "id=123", so url.query is "id=123" and prints correctly.
  3. Final Answer:

    Prints 'Open profile with id: id=123' and returns true -> Option D
  4. Quick Check:

    URL matches scheme and host, query printed [OK]
Hint: Check url.scheme and url.host before using url.query [OK]
Common Mistakes:
  • Assuming url.query is nil and causes crash
  • Ignoring url.host check
  • Returning false despite matching URL
4. Identify the error in this AppDelegate method for handling deep links:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
  if url.scheme = "myapp" {
    // handle URL
    return true
  }
  return false
}
medium
A. Using single equals (=) instead of double equals (==) in the if condition
B. Missing return statement inside the if block
C. Incorrect method signature missing default value for options
D. URL scheme comparison should use url.host instead

Solution

  1. Step 1: Check the if condition syntax

    The condition uses single equals (=) which is assignment, not comparison.
  2. Step 2: Understand correct comparison operator

    In Swift, equality check uses double equals (==), so this is a syntax error.
  3. Final Answer:

    Using single equals (=) instead of double equals (==) in the if condition -> Option A
  4. Quick Check:

    Comparison needs '==' not '=' [OK]
Hint: Use '==' for comparison, '=' is assignment [OK]
Common Mistakes:
  • Confusing assignment (=) with equality (==)
  • Ignoring method signature correctness
  • Mixing url.scheme and url.host in condition
5. You want to support universal links in your iOS app. Which of the following is NOT required for universal links to work correctly?
hard
A. Implementing application(_:open:options:) to handle the link
B. Hosting an apple-app-site-association file on your website
C. Adding associated domains capability in your app's entitlements
D. Configuring your website's HTTPS server with a valid certificate

Solution

  1. Step 1: Understand universal links requirements

    Universal links require a hosted apple-app-site-association file, entitlements setup, and HTTPS with valid certificate.
  2. Step 2: Identify handling method difference

    Universal links use NSUserActivity, not application(_:open:options:), which is for custom URL schemes.
  3. Final Answer:

    Implementing application(_:open:options:) to handle the link -> Option A
  4. Quick Check:

    Universal links use NSUserActivity, not open URL method [OK]
Hint: Universal links use NSUserActivity, not open URL method [OK]
Common Mistakes:
  • Thinking application(_:open:options:) handles universal links
  • Ignoring HTTPS requirement for universal links
  • Skipping apple-app-site-association file setup
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard