SwiftDeveloper SwiftDeveloper - 3 months ago 12
JSON Question

Swift do catch inside function doesn't work

I have a function which parses JSON, but I get a nil error dealing with the URL strings:

var jsonResponse: NSMutableDictionary?
do{
jsonResponse = try NSJSONSerialization.JSONObjectWithData(data!,
options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;

let info : NSArray = jsonResponse!.valueForKey("latest_receipt_info") as! NSArray
let transaction_id: String? = info[0].valueForKey("transaction_id") as? String
let purchase_date: String? = info[0].valueForKey("purchase_date") as? String
let product_id: String? = info[0].valueForKey("product_id") as? String
let web_order_line_item_id: String? = info[0].valueForKey("web_order_line_item_id") as? String

print("test")

// Send Values

let addIAPUrl:NSString = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
self.apiRequests(addIAPUrl as String, completionHandler: { (success, message) -> Void in

print("success \(addIAPUrl)")

if(success == 1){

dispatch_async(dispatch_get_main_queue()){

// ADDED
print("success \(addIAPUrl)")

}

}else{

// DONT ADDED
}



})


The output doesn't return any error but the function fails after print("test"). The apiRequests function works in other cases, but doesn't seem to work in this context.

I would appreciate any help finding the problem.

Here is the code for the
apiRequest
function:

func apiRequests(url : String, completionHandler : ((success : Int, message : String) -> Void)) {

guard let url = NSURL(string: url as String) else {

return
}

let urlRequest = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)

let task = session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) in
guard let responseData = data else {

return
}
guard error == nil else {

print(error)
return
}

let post: NSDictionary
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
} catch {

return
}

let numberFromString = Int((post["success"] as? String)!)


completionHandler(success: (numberFromString)!, message: (post["message"] as? String)!)



})
task.resume()

}

Answer

It seems to me that the problem is most likely that your apiRequests: function is erroring at one of many places, and is returning instead of calling your callback with an error state.

func apiRequests(url : String, completionHandler : ((success : Int, message : String) -> Void)) {

    guard let url = NSURL(string: url as String) else {
        completionHandler(0, "Couldn't get URL")
        return
    }

    let urlRequest = NSURLRequest(URL: url)
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config)

    let task = session.dataTaskWithRequest(urlRequest, completionHandler: { (data,  response, error) in
        guard let responseData = data else {
            completionHandler(0, "Data was nil")
            return
        }
        guard error == nil else {
            print(error)
            completionHandler(0, "Error wasn't nil")
            return
        }

        let post: NSDictionary
        do {
            post = try NSJSONSerialization.JSONObjectWithData(responseData,
                options: []) as! NSDictionary
        } catch  {
            completionHandler(0, "Error with NSJSONSerialization")
            return
        }

        let numberFromString = Int((post["success"] as? String)!)


        completionHandler(success: (numberFromString)!, message: (post["message"] as? String)!)



    })
    task.resume()

}

Side note, but not related to the fix,

 let addIAPUrl:NSString = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
 self.apiRequests(addIAPUrl as String, completionHandler: { (success, message) -> Void in

Can easily be replaced with

let addIAPUrl = "http://bla.com/application/addIAP.php?transaction_id=\(transaction_id!)&purchase_date=\(purchase_date)&product_id=\(product_id)&web_order_line_item_id=\(web_order_line_item_id)&userID=\(prefs.valueForKey("userID") as! String!)"
self.apiRequests(addIAPUrl, completionHandler: { (success, message) -> Void in

Because you are converting a String to an NSString then back to a String