Skip to content

MovableInk Link Resolution without SDK

Under the Signing & Capabilities tab, add the Associated Domains Capability if you don't already have it, then add the applinks that you can support. For example, if your MovableInk Domain is mi.example.com, you'd want to add applinks:mi.example.com.

associated domains example

UIKit

Apps using Scenes

Note

If your app is using iOS Scenes, use the following code below, otherwise you can you can skip forward to Apps not using Scenes section.

In your SceneDelegate, you can extract the URL that opened the app by:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let scene = (scene as? UIWindowScene) else { return }

    ...

    // Grab the user activity from the connection options
    if let userActivity = connectionOptions.userActivities.first {}
      handleUniversalLink(from: userActivity)
    }
  }

  // Implement this method
  func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    handleUniversalLink(from: userActivity)
  }

  // Attempt to handle the incoming link
  func handleUniversalLink(from userActivity: NSUserActivity) {
    // Get URL components from the incoming user activity 
    // and check if it matches your MovableInk Domain
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let incomingURL = userActivity.webpageURL,
          incomingURL.host == "mi.example.com"
    else {
      return 
    }

    Task {       
      do {
        // The incomingURL here is a MovableInk Link
        //
        // Make a URLRequest to this URL
        let request = URLRequest(url: url)
        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              case (200..<300) = httpResponse.statusCode,
              let url = httpResponse.url
        else {
          debugPrint("Could not resolve deeplink")

          if let error = String(data: data, encoding: .utf8) {
            debugPrint(error)
          }

          return
        }

        // This is the URL that the MovableInk Link resolved to
        debugPrint(url)
      } catch {
        debugPrint("An error occurred while attempting to resolve a Deeplink")
      }
    }
  }
}

Apps not using Scenes

In your AppDelegate, you can extract the URL that opened the app by:

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
  ) -> Bool {
    // Check if the URL is a MovableInk Link
    guard url.host == "mi.example.com" else { return false }

    handleUniversalLink(url: url)
    return true
  }

  func application(
    _ application: UIApplication, 
    continue userActivity: NSUserActivity, 
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
  ) -> Bool {
    // Get URL components from the incoming user activity 
    // and check if it matches your MovableInk Domain
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let incomingURL = userActivity.webpageURL,
          incomingURL.host == "mi.example.com"
    else {
      return false
    }

    handleUniversalLink(url: incomingURL)
    return true
  }

  // Attempt to handle the incoming link
  func handleUniversalLink(url: URL) {
    Task {       
      do {
        // The incomingURL here is a MovableInk Link
        //
        // Make a URLRequest to this URL
        let request = URLRequest(url: url)
        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              case (200..<300) = httpResponse.statusCode,
              let url = httpResponse.url
        else {
          debugPrint("Could not resolve deeplink")

          if let error = String(data: data, encoding: .utf8) {
            debugPrint(error)
          }

          return
        }

        // This is the URL that the MovableInk Link resolved to
        debugPrint(url)
      } catch {
        debugPrint("An error occurred while attempting to resolve a Deeplink")
      }
    }
  }
}

The above code snippets will only handle links that opened the app (Universal Links). If you also want to resolve links such as from a push notification or an In-App Message, you can get an idea of how you can do that here:

Resolving a MovableInk Link from a push notification

Resolving a MovableInk Link from an In-App Message

SwiftUI

On your App, you can add the onOpenURL modifier to get the URL that opened the app. You can follow the SwiftUI Deeplinking Solutions article to better understand how to take the resolved URL and access it on your other Views via the environment to update the UI.

@main
struct MyApp: App {
  var body: some Scene {
    MyView()
      .onOpenURL { url in
        guard url.host == "mi.example.com" else { return }

        Task {
          do {
            // The incomingURL here is a MovableInk Link
            //
            // Make a URLRequest to this URL
            let request = URLRequest(url: url)
            let (data, response) = try await URLSession.shared.data(for: request)

            guard let httpResponse = response as? HTTPURLResponse,
                  case (200..<300) = httpResponse.statusCode,
                  let url = httpResponse.url
            else {
              debugPrint("Could not resolve deeplink")

              if let error = String(data: data, encoding: .utf8) {
                debugPrint(error)
              }

              return
            }

            // This is the URL that the MovableInk Link resolved to
            debugPrint(url)
          } catch {
            debugPrint("An error occurred while attempting to resolve a Deeplink")
          }
        }
      }
  }
}