3

The following curl works

curl -G -H "api_key: MYAPIKEY" https://api.semantics3.com/test/v1/products -d 'q={"upc":"70411576937"}'

However, upon trying to convert it to iOS I get the following error:

Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." {NSErrorFailingURLStringKey=https://api.semantics3.com/test/v1/products,...}

I have attached my code below but I believe that my problem is the "q=" right before the json data that is being submitted to the URL. If so, what is this called and how do I put "q=" before my json data? I can't exactly tell though, due to iOS' unfaltering ability to provide us with unrelated error messages. Thank you.

    var urlString = "https://api.semantics3.com/test/v1/products"
    var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
    var response: NSURLResponse?
    var error: NSErrorPointer = nil
    var reqText = ["upc": "70411576937"]
    var err: NSError?

    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(reqText, options: nil, error: &err)
    request.HTTPMethod = "GET"
    request.addValue("MYAPIKEY", forHTTPHeaderField: "api_key")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    var session = NSURLSession.sharedSession()

    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
        if(err != nil) {
            println(err!.localizedDescription)
        }
        else {
            //this is where the error is printed
            println(error)
            var parseError : NSError?
            // parse data
            let unparsedArray: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &parseError)
            println(parseError)
            if let resp = unparsedArray as? NSDictionary {
                println(resp)
            }
        }
    })
    task.resume()
1
  • I know it sounds silly, but try quitting the simulator & running the app again. Sometimes my simulator loses its connection after a night or so sitting idle. Commented Jun 9, 2015 at 0:07

2 Answers 2

1

Body is not used in GET http methods. Use the following code to concat your params:

extension String {

    /// Percent escape value to be added to a URL query value as specified in RFC 3986
    ///
    /// This percent-escapes all characters besize the alphanumeric character set and "-", ".", "_", and "~".
    ///
    /// http://www.ietf.org/rfc/rfc3986.txt
    ///
    /// :returns: Return precent escaped string.

    func stringByAddingPercentEncodingForURLQueryValue() -> String? {
        let characterSet = NSMutableCharacterSet.alphanumericCharacterSet()
        characterSet.addCharactersInString("-._~")

        return self.stringByAddingPercentEncodingWithAllowedCharacters(characterSet)
    }

}

extension Dictionary {

    /// Build string representation of HTTP parameter dictionary of keys and objects
    ///
    /// This percent escapes in compliance with RFC 3986
    ///
    /// http://www.ietf.org/rfc/rfc3986.txt
    ///
    /// :returns: String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped

    func stringFromHttpParameters() -> String {
        let parameterArray = map(self) { (key, value) -> String in
            let percentEscapedKey = (key as! String).stringByAddingPercentEncodingForURLQueryValue()!
            let percentEscapedValue = (value as! String).stringByAddingPercentEncodingForURLQueryValue()!
            return "\(percentEscapedKey)=\(percentEscapedValue)"
        }

        return join("&", parameterArray)
    }

}


var urlString = "https://api.semantics3.com/test/v1/products"
var reqText = ["upc": "70411576937"]
var err: NSError?

let parameterString = reqText.stringFromHttpParameters()
let requestURL = NSURL(string:"\(urlString)?\(parameterString)")!

var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
var response: NSURLResponse?
var error: NSError?

request.HTTPMethod = "GET"
request.addValue("MYAPIKEY", forHTTPHeaderField: "api_key")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var session = NSURLSession.sharedSession()

PARTIAL EDIT: SWIFT 2.1 (updated)

extension Dictionary {

    func stringFromHttpParameters() -> String {
        let parameterArray = self.map { (key, value) -> String in
            let percentEscapedKey = (key as! String).stringByAddingPercentEncodingForURLQueryValue()!
            let percentEscapedValue = (value as! String).stringByAddingPercentEncodingForURLQueryValue()!
            return "\(percentEscapedKey)=\(percentEscapedValue)"
        }

        return parameterArray.joinWithSeparator("&")
    }

}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. My problem was that my NSURL was not recognizing the curly brackets, but the stringByAddingPercentEncodingForURLQueryValue() method fixed this for me.
With Swift 2 I'm getting an error on the second line in the extension Dictionary that says: "Cannot invoke 'map' with an argument list of type '(Dictionary<Key,Value),(,) -> String)" Any idea how to fix this?
I updated the Dictionary extension to compile with Swift 2.1. Still not quite sure why i had to break the function in two to compile. As soon as I declare a variable with let in the map's closure, the compiler complains. I may post another question just for that.
I think I found the problem. The closure needs to specify the return type which I believe it could infer from the code. This seems to be a bug in the compiler.
0

Convert your JSON to a string, prepend the q= to this, then convert the resulting string to Data before assigning it to the request's HTTPBody.

Something like this perhaps:

let array = [ "one", "two" ]
let data = NSJSONSerialization.dataWithJSONObject(array, options: nil, error: nil)
let body= "q=" + NSString(data: data!, encoding: NSUTF8StringEncoding)
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.