Skip to content

Instantly share code, notes, and snippets.

@algal
Created June 17, 2015 17:31
Show Gist options
  • Save algal/13ff4e78f1be42691d1b to your computer and use it in GitHub Desktop.
Save algal/13ff4e78f1be42691d1b to your computer and use it in GitHub Desktop.
Helper to encapsulate loading JSON over the network.
//
// MARK: generic networking and JSON-decoding helper
//
// give it a NSURLRequest and a session, it gives you back a aresult with an AnyObject or an NSError
public class JSONService
{
/// returns JSON result on statusCode 200, and an error otherwise
public class func taskWithJSONRequest(
request:NSURLRequest,
session:NSURLSession,
completion:(JSONResult)->()) -> NSURLSessionDataTask
{
let task = session.dataTaskWithRequest(request, completionHandler: {
(data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
if let error = error {
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Fail(error))
}
}
else {
// assert: sub-HTTP networking succeeded
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode < 200 || httpResponse.statusCode > 299 {
let error = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 0, userInfo: [NSLocalizedFailureReasonErrorKey : "http returned non-200 status code","result":httpResponse])
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Fail(error))
}
}
else {
// assert: ... and HTTP succeeded (200)
if let data = data {
var JSONError:NSError?
let JSONValue: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &JSONError)
if let JSONValue: AnyObject = JSONValue {
// assert: ... and JSON decoding succeeded
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Success(JSONValue))
}
}
else {
if let JSONError = JSONError {
// JSON decoding failed
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Fail(JSONError))
}
}
else {
Log_asWarn("ERROR: Apple violated its API contract. NSJSONSerialization.JSONObjectWithData returned a nil value, but did not populate its error object")
let myJSONError = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 0, userInfo: [NSLocalizedFailureReasonErrorKey :"NSJSONSerialization.JSONObjectWidthData returned nil and no error"])
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Fail(myJSONError))
}
}
}
}
}
}
else {
let errString = "ERROR: Apple violated its API contract. NSURLSession.dataTaskWithRequest returned a nil NSHTTPURLResponse object even though there was no NSError"
Log_asWarn(errString)
let myError = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 0, userInfo: [NSLocalizedFailureReasonErrorKey :errString])
dispatch_async(dispatch_get_main_queue()) {
completion(JSONResult.Fail(myError))
}
}
}
})
task.resume()
return task
}
public enum JSONResult {
case Success(AnyObject)
case Fail(NSError)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment