1

The task is quite simple. With a given urlString open it when it is valid. This is what I tried:

func openURL(_ urlString: String) {
    guard let url = URL(string: urlString) else {
        showInvalidUrlAlert()
        return
    }
    UIApplication.shared.open(url)
}

This work with this example: "https://www.google.de/?hl=de"

However when passing an invalid url, which is also possible in my application (for example: "asdfd") I get this error on the console but nothing happens in the app:

[default] Failed to open URL asdf: Error Domain=NSOSStatusErrorDomain Code=-50 "invalid input parameters" UserInfo={NSDebugDescription=invalid input parameters, _LSLine=252, _LSFunction=-[_LSDOpenClient openURL:options:completionHandler:]}

What is the best practice here?

Chris
  • 1,828
  • 6
  • 40
  • 108

3 Answers3

3

You may want to use the completionHandler parameter:

func openURL(_ urlString: String) {
    guard let url = URL(string: urlString) else {
        showInvalidUrlAlert()
        return
    }
    UIApplication.shared.open(url, completionHandler: { success in
        if success {
            print("opened")
        } else {
            print("failed")
            // showInvalidUrlAlert()
        }
    })
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • thanks, do I have to handle the `success` case somehow? – Chris Jul 26 '20 at 15:38
  • @Chris No, you can easily do `if !success { showInvalidUrlAlert() }` – pawello2222 Jul 26 '20 at 15:39
  • @Chris But this is another question and your edit changes the whole context. I'd suggest you remove your edit and post as a new question. I'll try to help you there. – pawello2222 Jul 26 '20 at 15:44
  • done: https://stackoverflow.com/questions/63102385/handle-completion-if-no-success-when-opening-url-with-safariviewcontroller – Chris Jul 26 '20 at 15:50
2

Did the URL have a http or https scheme attached? to open a website, you must require the String to have http(s). other wise the application won't know how to handle it, since it also handles other protocols.

...supports many common schemes, including the http, https, tel, facetime, and mailto schemes...

https://developer.apple.com/documentation/uikit/uiapplication/1648685-open

1

Inside of guard statement, you can throw an exception created by your application instead only put a return, like this:

guard let urlString = url, !urlString.isEmpty, let url = URL(string: urlString) else {
    throw ErrorEnum.invalidURL
}

With this approach, you can catch the error and send a UI Feedback for the User where it calls de func openURL.

Moreira L
  • 11
  • 1
  • but I am already sending back a feedback with `showInvalidUrlAlert` but thats not called with the example above.. – Chris Jul 26 '20 at 14:14
  • Is because is creating de `url` with the string `asdfd`, in this case, is falling in the moment to open for the App `UIApplication.shared.open(url)` ... is ugly, I know but the API is building de URL even is not a valid URL. – Moreira L Jul 26 '20 at 14:39
  • So Whats the way to Go Here? – Chris Jul 26 '20 at 14:41
  • You can create an extension for URL ... `extension URL: ExpressibleByStringLiteral`, like this approach here: https://www.hackingwithswift.com/example-code/language/how-to-make-custom-types-from-strings-using-expressiblebystringliteral, take a look. – Moreira L Jul 26 '20 at 14:42
  • Maybe this thread can help you https://stackoverflow.com/questions/28079123/how-to-check-validity-of-url-in-swift – Moreira L Jul 26 '20 at 16:17