13

On iOS, how can I programmatically determine if a URL is a Universal Link or just a regular web URL?

Let's say you are about to launch the URL http://www.yelp.com from your own iOS app. (http://www.yelp.com is a fully registered universal link.)

Case one) the user doesn't have the app installed -> You want to show them the website in an IN-APP webview.

Case two) the user does have the app installed -> You want to launch out of your app and deep link directly to the the yelp app by using [[UIApplication sharedApplication] openURL:URL]; instead of presenting a webview in app.

Here is the problem: All you get to work with is the string url: "http://www.yelp.com" Your goal is to launch out to the yelp app if installed but present an in-app webview if yelp is not installed.

Note 1: This question is only about universal links. Please do not give answers which use URL Schemes.

Note 2: This question is not about specifically launching the yelp app. The solution should work for any url to determine if it is a universal link of an installed app.

Can you do this?

Andrew Paul Simmons
  • 4,334
  • 3
  • 31
  • 39
  • Use canOpenURL method to check if URL’s scheme can be handled by the system, if it can't (yelp app not installed), then display webview screen. – nsinvocation Jan 10 '17 at 22:22
  • In what case will canOpenURL return false for the given url `http://www.yelp.com` ? (There is no scheme being discussed in this question, btw) – Andrew Paul Simmons Jan 10 '17 at 22:24

2 Answers2

12

Detect if a link is universal using UIApplicationOpenURLOptionUniversalLinksOnly

Following is the solution:

[[UIApplication sharedApplication] openURL:url
                                       options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @YES}
                             completionHandler:^(BOOL success){
                                 if(!success) {
                                     // present in app web view, the app is not installed 
                                 }
                             }];
Andrew Paul Simmons
  • 4,334
  • 3
  • 31
  • 39
2

I resolved this issue with my Swift 4 class below. It also uses embedded Safari Browser if possible. You can follow a similar method in your case too.

import UIKit
import SafariServices

class OpenLink {
    static func inAnyNativeWay(url: URL, dontPreferEmbeddedBrowser: Bool = false) { // OPEN AS UNIVERSAL LINK IF EXISTS else : EMBEDDED or EXTERNAL
        if #available(iOS 10.0, *) {
            // Try to open with owner universal link app
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : true]) { (success) in
                if !success {
                    if dontPreferEmbeddedBrowser {
                        withRegularWay(url: url)
                    } else {
                        inAnyNativeBrowser(url: url)
                    }
                }
            }
        } else {
            if dontPreferEmbeddedBrowser {
                withRegularWay(url: url)
            } else {
                inAnyNativeBrowser(url: url)
            }
        }
    }
    private static func isItOkayToOpenUrlInSafariController(url: URL) -> Bool {
        return url.host != nil && (url.scheme == "http" || url.scheme == "https") //url.host!.contains("twitter.com") == false
    }
    static func inAnyNativeBrowser(url: URL) { // EMBEDDED or EXTERNAL BROWSER
        if isItOkayToOpenUrlInSafariController(url: url) {
            inEmbeddedSafariController(url: url)
        } else {
            withRegularWay(url: url)
        }
    }
    static func inEmbeddedSafariController(url: URL) { // EMBEDDED BROWSER ONLY
        let vc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
        if #available(iOS 11.0, *) {
            vc.dismissButtonStyle = SFSafariViewController.DismissButtonStyle.close
        }
        mainViewControllerReference.present(vc, animated: true)
    }
    static func withRegularWay(url: URL) { // EXTERNAL BROWSER ONLY
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey(rawValue: "no"):"options"]) { (good) in
                if !good {
                    Logger.log(text: "There is no application on your device to open this link.")
                }
            }
        } else {
            UIApplication.shared.openURL(url)
        }
    }
}
Salih
  • 171
  • 1
  • 12