NSURL return nil while the URL is correct

Hi, I'm using a database to get some values, and i don't understand why the NSURL return nil. Here the code that works :

let urlString = "https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire?&apiKey=0HW9bYZVJEvmmV93Yo8jYADX3gWczJie"
print(urlString) // this return https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire?&apiKey=0HW9bYZVJEvmmV93Yo8jYADX3gWczJie
print(NSURL(string: urlString)) // return a thing


You can try the URL in the adress bar, it returns JSON, but when i tried to put a query inside, it doesn't work :

rlString = "https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire?q={\"lampadaire_id\":1}&apiKey=0HW9bYZVJEvmmV93Yo8jYADX3gWczJie"
print(urlString) // this return https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire?q={"lampadaire_id":1}&apiKey=0HW9bYZVJEvmmV93Yo8jYADX3gWczJie
print(NSURL(string: urlString)) // return nil


You can try the URL in the adress bar, it returns JSON too. I think it's because of the double quote in the query, how can I pass it please ?

Answered by guywithmazda in 137951022

You probably need to "escape" the string using % encoding. The old (deprecated but still allowed) is to use stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEndocding). The replacement is stringByAddingPercentEncodingWithAllowedCharacters(...). With the new way, there are predifined allowed character sets for each part of the url, such as NSCharacterSet.URLHostAllowedCharacterSet() and NSCharacterSet.URLQueryAllowedCharacterSet()

Accepted Answer

You probably need to "escape" the string using % encoding. The old (deprecated but still allowed) is to use stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEndocding). The replacement is stringByAddingPercentEncodingWithAllowedCharacters(...). With the new way, there are predifined allowed character sets for each part of the url, such as NSCharacterSet.URLHostAllowedCharacterSet() and NSCharacterSet.URLQueryAllowedCharacterSet()

guywithmazda has some great suggestions but I wanted to point out an alternative. The way I handle this sort of this is via NSURLComponents. That takes all the guesswork out of this process.

For example:

import Foundation

let components = NSURLComponents(string: "https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire")!
components.queryItems = [
    NSURLQueryItem(name: "q", value: "{\"lampadaire_id\":1}"),
    NSURLQueryItem(name: "apiKey", value: "0HW9bYZVJEvmmV93Yo8jYADX3gWczJie")
]
print(components.URL!)
// https://api.mlab.com/api/1/databases/lampadaire/collections/lampadaire?q=%7B%22lampadaire_id%22:1%7D&apiKey=0HW9bYZVJEvmmV93Yo8jYADX3gWczJie

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks eskimo, your answer works too, but the guywithmazda's answer is easier and faster for me ;p

That works well, thanks.

NSURL return nil while the URL is correct
 
 
Q