We have a today widget to deep link into the app. The deep links work just fine when the user accesses the widget from the home screen. However, when a user accesses the widget when the device is locked, or when the user slides down from the top of the screen, the links open in Safari.
I was wondering if anyone else has come across this issue, and if so, how they solved it.
Here was the solution we came upon (Swift 4.1). We needed to support a custom URL scheme to tell iOS that we can open links from the today widget. This uses a different UIApplication delegate function. Along with implementing func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool
, we also need to implement func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
First, in Info.plist
, we have our supported schemes under CFBUndleURLTypes
.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>todayWidgetScheme</string>
</array>
</dict>
</array>
Then, also in Info.plist
, we also listed the scheme under LSApplicationQueriesSchemes
.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>todayWidgetScheme</string>
</array>
Next, when opening the link from the today widget, set the url scheme to the iOS recognized todayWidgetScheme.
func openAppFromTodayWidget() {
if let url = URL(string: "https://url.com") {
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)
components?.scheme = "todayWidgetScheme"
if let todayWidgetUrl = components?.url {
extensionContext?.open(todayWidgetUrl)
}
}
}
Finally, in AppDelegate.swift
, when iOS asks the application to handle the universal link, set the original url scheme
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if url.scheme == "todayWidgetScheme" {
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)
components?.scheme = "https"
if let todayWidgetUrl = components?.url {
// do your thing
return true
}
}
return false
}