Skip to content

Instantly share code, notes, and snippets.

@egcode
Created April 14, 2017 01:50
Show Gist options
  • Select an option

  • Save egcode/25076f88e078df6842ff55df2c10fbbe to your computer and use it in GitHub Desktop.

Select an option

Save egcode/25076f88e078df6842ff55df2c10fbbe to your computer and use it in GitHub Desktop.
import Foundation
enum Crud:String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
}
open class APIResponse: CustomDebugStringConvertible {
open var code:Int
open var success:Bool
open var rawData:AnyObject?
open var data:Dictionary<String,AnyObject>?
open var dataArray:Array<Dictionary<String, AnyObject>>?
open var multiDataArray:Array<Array<Dictionary<String, AnyObject>>>?
open var dataNum:Int?
open var dataString:String?
open var error:NSError?
open let request:URLRequest?
open let duration:TimeInterval
open var token:String?
open var id:String?
init(request:URLRequest?, duration:TimeInterval, payload:AnyObject?, error:NSError?){
self.code = -1
self.success = false
self.data = nil
self.error = nil
self.request = request
self.duration = duration
self.token = nil
self.id = nil
if(error != nil){
self.error = error
}
else if let obj = payload {
self.rawData = obj
if let dict = obj as? Dictionary<String,AnyObject> {
if let data = dict["data"] as? Dictionary<String, AnyObject> {
self.data = data
} else if let data = dict["data"] as? Array<Dictionary<String, AnyObject>> {
self.dataArray = data
} else if let data = dict["data"] as? Array<Array<Dictionary<String, AnyObject>>> {
self.multiDataArray = data
} else if let data = dict["data"] as? String {
self.dataString = data
} else if let data = dict["data"] as? [Int] {
if data.count > 0{
self.dataNum = data[0]
}
}
}
}
// print(self.debugDescription)
if self.success == false {
// print(self.request!.cURL())
}
}
open var debugDescription: String {
let icon = self.success ? "✅" : "🚫"
var descr = "\(icon) <APIResponse"
if let r = self.request, let u = r.url, let m = r.httpMethod {
descr += " \(m) \(u)"
}
descr += " success=\(self.success) code=\(self.code)"
if let err = self.error {
descr += " error=\(err)"
}
let d = NSString(format: "%.2f", self.duration)
return descr + " duration=\(d)s>"
}
}
open class API {
//Get
open class func get(_ url:AnyObject, userToken:String?, completed: @escaping (_ response:APIResponse) -> Void) {
self.createURLRequest(url, method: .get, userToken: userToken, payload: nil, completed: completed)
}
//Post
open class func post(_ url:AnyObject, payload:[String:AnyObject]? = nil, userToken:String?, completed: @escaping (_ response:APIResponse) -> Void) {
self.createURLRequest(url, method: .post, userToken: userToken, payload: payload, completed: completed)
}
//Put
open class func put(_ url:AnyObject, payload:[String:AnyObject]? = nil, userToken:String?, completed: @escaping (_ response:APIResponse) -> Void) {
self.createURLRequest(url, method: .put, userToken: userToken, payload: payload, completed: completed)
}
//Delete
open class func delete(_ url:AnyObject, payload:[String:AnyObject]? = nil, userToken:String?, completed: @escaping (_ response:APIResponse) -> Void) {
self.createURLRequest(url, method: .delete, userToken: userToken, payload: payload, completed: completed)
}
fileprivate class func createURLRequest(_ u:AnyObject, method: Crud, userToken:String?, payload:[String:AnyObject]? = nil, completed: @escaping (_ response:APIResponse) -> Void) -> Void {
let startTime = Date()
let url:URL
if let ur = u as? URL {
url = ur
} else if let ur = u as? String, let uu = URL(string: ur) {
url = uu
} else {
completed(APIResponse(request: nil, duration: 0, payload: nil, error: nil))
return
}
let request = NSMutableURLRequest(url: url)
//If Token
if let token = userToken {
print("\nAPI \(method) \(url) with token \(token)")
request.addValue(token, forHTTPHeaderField: "x-access-token")
}
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpMethod = method.rawValue
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30
if method != .get {
if let pl = payload {
do {
request.httpBody = try JSONSerialization.data(withJSONObject: pl, options: JSONSerialization.WritingOptions())
} catch let error as NSError {
magic("Error in request post: \(error)")
request.httpBody = nil
} catch {
magic("Catch all error: \(error)")
}
}
}
URLSession.shared.dataTask(with: request as URLRequest) {data, response, error in
//in case of error
if error != nil {
magic(error)
completed(APIResponse(request: request as URLRequest, duration: Date().timeIntervalSince(startTime), payload: nil, error: error as NSError?))
return
} else {
guard let httpResponse = response as? HTTPURLResponse else{ magic("response error"); return }
guard let data = data else { magic("error getting data"); return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
var obj = [String:AnyObject]()
obj["data"] = json as AnyObject?
//Response
let apiResponse = APIResponse(request: request as URLRequest, duration: Date().timeIntervalSince(startTime), payload: obj as AnyObject?, error: error as NSError?)
//token if exists
apiResponse.code = httpResponse.statusCode
apiResponse.success = API.statusSuccessChecker(httpResponse.statusCode)
completed(apiResponse)
} catch {
print("Json Error:\(error)")
completed(APIResponse(request: request as URLRequest, duration: Date().timeIntervalSince(startTime), payload: nil, error: nil))
}
}
}.resume()
}
fileprivate class func statusSuccessChecker(_ code:Int) -> Bool {
var success = false
if code == 200 || code == 201 {
success = true
}
return success
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment