0

I'm adding deep linking to my app and getting stuck at handing off the URL to the view controller. I try to use notification but it doesn't work all the times.

My App Delegate:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {  
        let notification = Notification(name: "DeepLink", object: url)
        NotificationCenter.default.post(notification)

        return true
    }
}

And View Controller:

class ViewController: UIViewController {
    func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.handleDeepLink), name: "DeepLink", object: nil)
    }

    @objc private func handleDeepLink(notification: Notification) {
        let url = notification.object as! URL
        print(url)
    }
}

Problem: when my app is cold launched the notification is not handled, which I guess is due to the View Controller not having time to register itself as the observer yet. If I press the Home button, go to Notes and click on the deep link a second time, everything works as it should.

Question: how can I register the View Controller to observe the notification when the app is cold launched? Or is there a better way to send the URL from the App Delegate to the View Controller?

Mike Henderson
  • 2,028
  • 1
  • 13
  • 32

3 Answers3

1

I think an initial assumption is to assume your view controller does not have time to register itself which means that the connection between URL and View controller must be decoupled and reside outside of the view controller.

I would then use some kind of lookup to instantiate the view controller when a URL is received.

For example,

if url.contains(“x”) {
  let vc = ViewController(...)
  cv.url = URL // Pass contextual data to the view controller.
  // Present or push cv
}

As your app gets more complex you have to manage more challenging scenarios, like standing-up entire controller stacks, or removing presented controllers.

Scott McKenzie
  • 16,052
  • 8
  • 45
  • 70
0

I followed the example in the LaunchMe app. Here's what solved my problem:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    // My root view controller is a UINavigationController
    // Cast this to whatever class your root view controller is
    guard let navigationController = self.window?.rootViewController as? UINavigationController else {
        return false
    }

    // Navigate to the view controller that handles the URL within the navigation stack
    navigationController.popToRootViewController(animated: false)

    // Handle the URL
    let vc = navigationController.topViewController as! ViewController
    vc.handleDeepLink(url: url)
    return true
}
Mike Henderson
  • 2,028
  • 1
  • 13
  • 32
-1

Store if notification is not handled and load it when viewDidLoad.

var pendingNotificationInfo: PushNotificationInfo?
hojin
  • 1,221
  • 14
  • 16