Search code examples
iosswiftyelp

How to retrieve response JSON data with Swift


I am trying to use the Yelp API and receive the corresponding JSON according to a search term. Here is the YelpAPI Client I am using:

import Foundation
import UIKit

let yelpConsumerKey = "KLGXXXXfnmhQ"
let yelpConsumerSecret = "wPmXXXXvOA"
let yelpToken = "0-3DsXXXXhAq"
let yelpTokenSecret = "BViXXXXQ-Dz3Y"

class YelpClient: BDBOAuth1RequestOperationManager {
    var accessToken: String!
    var accessSecret: String!

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    class var sharedInstance : YelpClient {
        struct Static {
            static var token : dispatch_once_t = 0
            static var instance : YelpClient? = nil
        }
        dispatch_once(&Static.token) {
            Static.instance = YelpClient(consumerKey: yelpConsumerKey, consumerSecret: yelpConsumerSecret, accessToken: yelpToken, accessSecret: yelpTokenSecret)
        }
        return Static.instance!
    }

    init(consumerKey key: String!, consumerSecret secret: String!, accessToken: String!, accessSecret: String!) {
        self.accessToken = accessToken
        self.accessSecret = accessSecret
        var baseUrl = NSURL(string: "http://api.yelp.com/v2/")
        super.init(baseURL: baseUrl, consumerKey: key, consumerSecret: secret);

        var token = BDBOAuthToken(token: accessToken, secret: accessSecret, expiration: nil)
        self.requestSerializer.saveAccessToken(token)
    }

    func searchWithTerm(term: String, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, NSError!) -> Void) -> AFHTTPRequestOperation! {
        // For additional parameters, see http://www.yelp.com/developers/documentation/v2/search_api
        var parameters = ["term": term, "ll": "37.77493,-122.419415"]
        return self.GET("search", parameters: parameters, success: success, failure: failure)
    }

    func searchWithTerm(term: String, deal: Bool, radius: Int, sort: Int, categories: String, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, NSError!) -> Void) -> AFHTTPRequestOperation! {
        // For additional parameters, see http://www.yelp.com/developers/documentation/v2/search_api
        var parameters = NSDictionary()
        if (radius == -1) {
            parameters = ["term": term, "ll": "37.77493,-122.419415", "deals_filter": deal, "sort": sort, "category_filter":categories]
        }
        else {
            var meter:Double = Double(radius) * 1609.34
            parameters = ["term": term, "ll": "37.77493,-122.419415", "deals_filter": deal, "radius_filter": meter, "sort": sort, "category_filter":categories]
        }
        return self.GET("search", parameters: parameters as [NSObject : AnyObject], success: success, failure: failure)
    }


}

I made a model class for the restaurants here:

import UIKit

class Resturant: NSObject {
    var name: String!
    var thumbUrl: String!
    var address: String!
    var jsonData: NSData!

    init(dictionary: NSDictionary) {
        name = dictionary["name"] as? String
        thumbUrl = dictionary["thumbUrl"] as? String
        address = dictionary["address"] as? String
    }

    class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
        YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
            println(response)
        let JSONObject = NSJSONSerialization.JSONObjectWithData(response as! NSData, options: NSJSONReadingOptions(0), error: nil)
            }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in

        }
    }
}

let JSONObject = NSJSONSerialization.JSONObjectWithData(response as! NSData, options: NSJSONReadingOptions(0), error: nil)

This line of code prompts this error:

Could not cast value of type '__NSCFDictionary' (0x10b914a60) to 'NSData' (0x10b913a48).


Solution

  • You ARE getting the response JSON. It's just that it is a binarized NSData object which you would want to convert to JSON object, if I am not wrong. Right now, I guess it will print illegible blocks of alpha numeric characters, right?

    Well, you can do something like:

    class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
            YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
                println(response) //Illegible block of data
                let JSONObject = NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions(0), error: nil)
                 println(JSONObject)//Prints JSON
    
                }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
    
            }
        }
    

    EDIT #1

    Looks like it is the case of bad request. Be clear about the contract between the client and the server for this work. There must be some parameter that might be missing or something unexpected request. I'm afraid we cannot help you as we do not know what that contract is.

    EDIT #2

    At this point of code ...

    let JSONObject = NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions(0), error: nil)
    

    ... the API accepts the response type as NSData. But, your response type is NSDictionary. It would be giving you a warning; however there is no type checking at the compile time, it compiles. But the runtime is trying to treat response as NSData, but it is not; it is actually a NSDictionary, crashes.

    Just log the NSDictionary. You'll get the results.

    Edit #3 Your final code should like this:

    class func searchWithQuery(query: String, completion: ([Resturant]!, NSError!) -> Void) {
                YelpClient.sharedInstance.searchWithTerm(query, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
                    println(response) //Illegible block of data
                    let responseInfo = response as! NSDictionary
                    println(responseInfo)
                    //Prints JSON
    
                    }) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
    
                }
            }