Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFSafariViewController crash: The specified URL has an unsupported scheme

My code:

if let url = NSURL(string: "www.google.com") {
    let safariViewController = SFSafariViewController(URL: url)
    safariViewController.view.tintColor = UIColor.primaryOrangeColor()
    presentViewController(safariViewController, animated: true, completion: nil)
}

This crashes on initialization only with exception:

The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported

When I use url = NSURL(string: "http://www.google.com"), everything is fine. I am actually loading URL's from API and hence, I can't be sure that they will be prefixed with http(s)://.

How to tackle this problem? Should I check and prefix http:// always, or there's a workaround?

like image 570
Sahil Kapoor Avatar asked Sep 30 '15 10:09

Sahil Kapoor


4 Answers

Try checking scheme of URL before making an instance of SFSafariViewController.

Swift 3:

func openURL(_ urlString: String) {
    guard let url = URL(string: urlString) else {
        // not a valid URL
        return
    }

    if ["http", "https"].contains(url.scheme?.lowercased() ?? "") {
        // Can open with SFSafariViewController
        let safariViewController = SFSafariViewController(url: url)
        self.present(safariViewController, animated: true, completion: nil)
    } else {
        // Scheme is not supported or no scheme is given, use openURL
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
}

Swift 2:

func openURL(urlString: String) {
    guard let url = NSURL(string: urlString) else {
        // not a valid URL
        return
    }

    if ["http", "https"].contains(url.scheme.lowercaseString) {
        // Can open with SFSafariViewController
        let safariViewController = SFSafariViewController(URL: url)
        presentViewController(safariViewController, animated: true, completion: nil)
    } else {
        // Scheme is not supported or no scheme is given, use openURL
        UIApplication.sharedApplication().openURL(url)
    }
}
like image 200
alanhchoi Avatar answered Oct 29 '22 14:10

alanhchoi


You can check for availability of http in your url string before creating NSUrl object.

Put following code before your code and it will solve your problem (you can check for https also in same way)

var strUrl : String = "www.google.com"
if strUrl.lowercaseString.hasPrefix("http://")==false{
     strUrl = "http://".stringByAppendingString(strUrl)
}
like image 36
Yuvrajsinh Avatar answered Oct 29 '22 15:10

Yuvrajsinh


I did a combination of Yuvrajsinh's & hoseokchoi's answers.

func openLinkInSafari(withURLString link: String) {

    guard var url = NSURL(string: link) else {
        print("INVALID URL")
        return
    }

    /// Test for valid scheme & append "http" if needed
    if !(["http", "https"].contains(url.scheme.lowercaseString)) {
        let appendedLink = "http://".stringByAppendingString(link)

        url = NSURL(string: appendedLink)!
    }

    let safariViewController = SFSafariViewController(URL: url)
    presentViewController(safariViewController, animated: true, completion: nil)
}
like image 10
Dylan Avatar answered Oct 29 '22 14:10

Dylan


Use WKWebView's method (starting iOS 11),

class func handlesURLScheme(_ urlScheme: String) -> Bool
like image 4
infiniteLoop Avatar answered Oct 29 '22 14:10

infiniteLoop