If you have been playing with the links in the test page, you are aware that the two UIKit apps are not responding to the query arguments. The three “traffic lights” remain gray, no matter what we send.
That’s because we need to add another delegate call, to each one.
Yet Another Place To Catch Input
I am not aware of the technical reasons, but, when you open an app via Universal Links, the usual calls (application(_, open, options)
, for App Delegate, and scene(_, openURLContexts)
and scene(_, willConnectTo, options)
for Scene Delegate) are not called.
Instead, the system calls application(_, continue, restorationHandler)
, for App Delegate, and scene(_, continue)
, for Scene Delegate.
So we have to add these.
The App Delegate Target
Let’s add the method to our App Delegate target first.
Open the SimpleAppDelegate.swift
file, and, just below the application(_, open, options)
method, add the following code:
func application(_ inApplication: UIApplication, continue inUserActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
guard inUserActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = inUserActivity.webpageURL
else { return false }
return application(inApplication, open: url)
}
This simply picks the URL out of the input activity, and calls the existing method to execute it.
The App Delegate now works. Give it a try. Run it on the simulator, and use the links in the test page. All of the links under App Delegate will open the app. The Universal Link ones won’t ask if you want to open the app.
The Scene Delegate Target
Now, we’ll do the Scene Delegate target.
Open the SceneAppDelegate.swift
file, and, under the scene(_, willConnectTo, options)
method, add the following code:
func scene(_: UIScene, continue inUserActivity: NSUserActivity) {
guard inUserActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = inUserActivity.webpageURL
else { return }
var status: AppStatus = .off
if let statusString = url.query(),
let tempStatus = AppStatus(rawValue: statusString) {
status = tempStatus
}
currentViewController?.updateUI(status: status)
}
Yeah, DRY says that we should factor out a URL handler, but this is just a quick demo, so I’ll just copy/pasta.
Run the app on the simulator, and try out the Scene Delegate links in the test page.
Conclusion
If you use the test page, every link will work properly.
Of course, this is a very humble implementation. It’s barely useful. However, it does work, and will help you to have gone past some of the more frustrating and time-consuming parts of implementing URL Schemes and Universal Links.
It’s always good to have a working example on hand, to reference, when things aren’t going as planned.
There’s a lot more power in these APIs, and you’ll be able to do a great deal more with them, in your own implementations.
Good luck!
Here is a release with the complete solution.
References and Further Reading
- Apple Documentation on URL Schemes
- Apple URL Scheme Reference
- Apple’s General Document on Universal Linking
- Apple Documentation on Specific Universal Link Support
- Apple Documentation on Associated Domains
- Apple Documentation With List of Associated Domain Entitlement Services
- Apple Documentation on the Applinks Associated Domain Entitlement
- An Excellent Apple Technote on Debugging Universal Links