Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // APIResource.swift
- // CEPU
- //
- // Created by Elvis Ametov on 24/01/18.
- // Copyright © 2018 CEPU. All rights reserved.
- //
- import Foundation
- import Alamofire
- import ObjectMapper
- protocol APIResource {
- var request: APIRequest { get }
- }
- extension APIResource {
- @discardableResult
- func responseData(_ completionHandler: @escaping ResponseHandlerBlock) -> Request? {
- return self.pureRequest(completionHandler: completionHandler)
- }
- @discardableResult
- func responseJSON(completionHandler: @escaping (_ json: Any?, _ error: NSError?) -> Void) -> Request? {
- return self.pureRequest(completionHandler: { (data, error) in
- do {
- guard error == nil else {
- completionHandler(nil, error)
- return
- }
- let JSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
- completionHandler(JSON, nil)
- } catch {
- completionHandler(nil, error as NSError)
- }
- })
- }
- @discardableResult
- func responseObject<T: Mappable>(_ mappingType: T.Type, keyPath: String? = nil, completionHandler: @escaping (_ object: T?, _ error: NSError?) -> Void) -> Request? {
- return self.responseJSON(completionHandler: { (json, error) in
- guard error == nil else {
- completionHandler(nil, error)
- return
- }
- var json = json as! [String : Any]?// swiftlint:disable:this force_cast
- if let keyPath = keyPath {
- if json != nil {
- if let js = json {
- if let js1 = js[keyPath] as? [String: Any] {
- json = js1
- } else {
- }
- }
- }
- }
- if let parsedObject = Mapper<T>().map(JSON: json!) {
- completionHandler(parsedObject, nil)
- return
- }
- print("ObjectMapper failed to serialize response.")
- completionHandler(nil, APIError.standard(reason: "ObjectMapper failed to serialize response."))
- })
- }
- @discardableResult
- func responseObjectArray<T: Mappable>(_ mappingType: T.Type, keyPath: String? = nil, completionHandler: @escaping (_ objects: [T]?, _ error: NSError?) -> Void) -> Request? {
- return self.responseJSON(completionHandler: { (json, error) -> Void in
- guard error == nil else {
- completionHandler(nil, error)
- return
- }
- var jsonToMap: [[String : Any]]?
- if let keyPath = keyPath {
- // jsonToMap = (json as! [String : Any]?)![keyPath] as! [[String : Any]]?
- if let json = json as? [String: Any] {
- if let js = json[keyPath] as? [[String: Any]] {
- jsonToMap = js
- }
- }
- } else {
- jsonToMap = json as! [[String : Any]]?// swiftlint:disable:this force_cast
- }
- if let jsonToMap = jsonToMap {
- let parsedObject = Mapper<T>(context: nil).mapArray(JSONArray: jsonToMap)
- if parsedObject.isEmpty {
- print("Response object array is empty!")
- }
- completionHandler(parsedObject, nil)
- } else {
- completionHandler(nil, APIError.standard(reason: "ObjectMapper failed to serialize response."))
- }
- })
- }
- }
- typealias ResponseHandlerBlock = (_ data: Data?, _ error: NSError?) -> Void
- extension APIResource {
- @discardableResult
- fileprivate func pureRequest(completionHandler: @escaping ResponseHandlerBlock) -> Request? {
- var request: DataRequest
- guard NetworkReachabilityManager()!.isReachable else {
- let error = NSError(domain: APIError.domain, code: APIError.connectionErrorCode, userInfo: [NSLocalizedFailureReasonErrorKey: "Connection error"])
- completionHandler(nil, error)
- return nil
- }
- guard !self.request.shouldUpload else {
- if let params = self.request.params {
- SessionManager.default.upload(multipartFormData: { (formData) in
- for (index, image) in self.request.images.enumerated() {
- formData.append(image, withName: "anyNameOfFile", fileName: "image\(index).jpg", mimeType: "image/jpeg")
- }
- for (key, value) in params {
- if let data = "\(value)".data(using: String.Encoding.utf8) {
- formData.append(data, withName: key)
- }
- }
- }, to: self.request, method: .put, headers: API.additionalHeaders, encodingCompletion: { (result) in
- switch result {
- case .success(let upload, _, _):
- upload.responseJSON { response in
- self.serializeResponse(response: response.defaultDataResponse, completionHandler: completionHandler)
- }
- case .failure(let encodingError):
- completionHandler(nil, encodingError as NSError)
- }
- })
- }
- return nil
- }
- request = SessionManager.default.request(self.request)
- request = request.validate(statusCode: 200...204).validate(contentType: ["application/json"])
- request.response(queue: DispatchQueue.main, completionHandler: { (response) -> Void in
- // logging response
- self.serializeResponse(response: response, completionHandler: completionHandler)
- })
- return request
- }
- private func serializeResponse(response: DefaultDataResponse, completionHandler: @escaping ResponseHandlerBlock) {
- do {
- if let json = try JSONSerialization.jsonObject(with: response.data!, options: .allowFragments) as? [String: AnyObject] {
- print("Response:\n\(json)\n")
- } else if let json = try JSONSerialization.jsonObject(with: response.data!, options: .allowFragments) as? [AnyObject] {
- print("Response:\n\(json)\n")
- }
- } catch {
- print(response.error?.localizedDescription ?? "Response error!!!")
- }
- let serializedError = Self.errorSerializer(data: response.data, error: response.error as NSError?, response: response.response)
- guard serializedError == nil else {
- return completionHandler(nil, serializedError)
- }
- completionHandler(response.data, nil)
- }
- fileprivate static func errorString(_ json: [String: AnyObject]) -> String? {
- if let error = json["error"] as? [String: Any] {
- if let errorString = error["toUserDisplay"] as? String {
- return errorString
- } else if let errorString = error["summaryDescription"] as? String {
- return errorString
- } else {
- return APIError.unknown.localizedDescription
- }
- }
- if let errorString = json["error"] as? String {
- return errorString
- }
- return nil
- }
- fileprivate static func errorMessage(_ error: NSError?, response: HTTPURLResponse?, data: Data?) -> NSError? {
- if let response = response {
- if 200...204 ~= response.statusCode || response.statusCode == 404 || response.statusCode == 422 || response.statusCode == 426 {
- var errorMessage: String?
- if let data = data, !data.isEmpty {
- do {
- guard let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: AnyObject] else {
- return nil
- }
- errorMessage = self.errorString(json)
- guard errorMessage != nil else {
- return nil
- }
- } catch {}
- }
- return self.extractError(error, response: response, errorMessage: errorMessage)
- }
- }
- return error
- }
- fileprivate static func extractError(_ error: NSError?, response: HTTPURLResponse, errorMessage: String?) -> NSError {
- if error != nil {
- if let errorMessage = errorMessage {
- var userInfo = error!.userInfo
- userInfo["NSLocalizedFailureReason"] = errorMessage
- let err = NSError(domain: error!.domain, code: response.statusCode, userInfo: userInfo)
- return err
- }
- let err = NSError(domain: error!.domain, code: response.statusCode, userInfo: error!.userInfo)
- return err
- } else {
- let userInfo = ["NSLocalizedFailureReason": errorMessage ?? ""]
- let err = NSError(domain: "error.domain", code: response.statusCode, userInfo: userInfo)
- return err
- }
- }
- fileprivate static func errorSerializer(data: Data?, error: NSError?, response: HTTPURLResponse?) -> NSError? {
- if let error = self.errorMessage(error, response: response, data: data) {
- return error
- }
- if let response = response, response.statusCode >= 200 && response.statusCode <= 204 {
- return nil
- }
- if let error = error {
- return error
- }
- guard let validData = data, !validData.isEmpty else {
- let failureReason = "JSON could not be serialized. Input data was nil or zero length."
- print(failureReason)
- return APIError.standard(reason: failureReason)
- }
- do {
- // JSON error parsing
- if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: AnyObject] {
- if let errorDic = json["error"] as? [String: AnyObject], let errorMessage = errorDic["message"] as? String {
- print(errorMessage)
- return APIError.standard(reason: errorMessage)
- }
- }
- } catch {
- return error as NSError
- }
- guard error == nil else {
- return error
- }
- return nil
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement