2

I have a button that, when pressed, it should take you to a url composed with some variables. All the variables are one word except "texto".

If "texto" is one word, all works ok. The problem comes when "texto" is more than one word (even a word and a space), and the button does not take you to url.

My code is the following:

@IBAction func pay(_ sender: Any) {

        NSLog("%@", texto);

        let urlString:String = "https://webpage/video.php?user=\(user)&pass=\(pass)&texto=\(texto)&esp=\(espec)&l_origen=\(l_origen)&l_destino=\(l_destino)"

        if let url = URL(string:urlString){
            let svc = SFSafariViewController(url: url)
            self.present(svc, animated: true, completion: nil)
        }
    } 
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Siens Imac
  • 35
  • 5

3 Answers3

0

You string should be percentage encoded

Do it like this

    let urlString:String = "https://webpage/video.php?user=\(user)&pass=\(pass)&texto=\(texto)&esp=\(espec)&l_origen=\(l_origen)&l_destino=\(l_destino)"
    let escapedString = urlString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

after that use escapedString to generate url from string

   if let url = URL(string:escapedString){
        let svc = SFSafariViewController(url: url)
        self.present(svc, animated: true, completion: nil)
    }
Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98
  • Now when I click the button I get the following error: 2018-03-13 12:59:02.295457+0100 SiensApp[3055:247139] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported.' – Siens Imac 22 mins ago – Siens Imac Mar 13 '18 at 12:24
  • No, that's wrong. You should not escape the whole URL - just the parts you are adding that might contain illegal characters. See my answer. – Duncan C Mar 13 '18 at 12:46
  • @DuncanC Thanks but is it really matters ? – Prashant Tukadiya Mar 13 '18 at 12:53
0

Use url encoding method as you cannot use spaces or special characters in url... Edited as per @Duncan C's suggestion.

let escapedTextTo = texto.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
print("texto = ", escapedTextTo);

let urlString:String = "https://webpage/video.php?user=\(user)&pass=\(pass)&texto=\(escapedTextTo)&esp=\(espec)&l_origen=\(l_origen)&l_destino=\(l_destino)"

if let url = URL(string:urlString){
   ...
}
Arnab
  • 4,216
  • 2
  • 28
  • 50
  • I tried your code, I had to add a '!' in: `urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!`. – Siens Imac Mar 13 '18 at 12:00
  • Now when I click the button I get the following error: 2018-03-13 12:59:02.295457+0100 SiensApp[3055:247139] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported.' – Siens Imac Mar 13 '18 at 12:00
  • Please check the url that you're using... probably it doesn't have any http:// or https:// – Arnab Mar 13 '18 at 12:09
  • Then I dont think you'll be able to use `SFSafariViewController`... or you can add that before the url. check this for ref: https://stackoverflow.com/questions/32864287/sfsafariviewcontroller-crash-the-specified-url-has-an-unsupported-scheme#35458932 – Arnab Mar 13 '18 at 12:44
  • No, that's wrong. You should not escape the whole URL - just the parts you are adding that might contain illegal characters. See my answer. – Duncan C Mar 13 '18 at 12:46
0

As others have said, spaces are not allowed in URLs. You have to "percent escape" any field that contains a space. However, you do not want to percent escape the entire URL, because that will escape characters like slashes, colons, and ampersands that are part of the grammar of the URL.

Your code should look like this:

@IBAction func pay(_ sender: Any) {

    let escapedTextTo = texto.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
    print("texto = ", escapedTextTo);

    let urlString:String = "https://webpage/video.php?user=\(user)&pass=\(pass)&texto=\(escapedTextTo)&esp=\(espec)&l_origen=\(l_origen)&l_destino=\(l_destino)"

    if let url = URL(string:urlString){
        let svc = SFSafariViewController(url: url)
        self.present(svc, animated: true, completion: nil)
    }
} 


Note that it's better to create your URL using URLComponents. It takes care of the different escaping rules for the various parts of the URL for you.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you, it worked and I completely understood your reasoning – Siens Imac Mar 13 '18 at 12:30
  • Note that based on some testing I just did, you should probably change the escaping to use `urlQueryAllowed` instead of `urlHostAllowed` (`texto.addingPercentEncoding(withAllowedCharacters: . urlQueryAllowed)!`) – Duncan C Mar 13 '18 at 12:45
  • If you escape with `urlHostAllowed`, it allows characters like `&` and `=` that are not legal in that location because they are query delimiters. – Duncan C Mar 13 '18 at 12:48
  • @DuncanC Good answer but only one issue should not forcefully unwrap that might create crash :) – Prashant Tukadiya Mar 13 '18 at 12:54
  • @PrashantTukadiya while the `addingPercentEncoding(withAllowedCharacters:)` function can **technically** fail, it won't in practice. (It will only fail if the underlying UTF16 contains invalid code pairs. If that fails the URL is going to fail anyway. – Duncan C Mar 13 '18 at 18:20