Last active
June 19, 2020 07:37
-
-
Save jdmcd/7126d39220b88500fcb8f9f6f8f3b30b to your computer and use it in GitHub Desktop.
Alamofire + Codable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class API { | |
static let apiKey = "test" | |
static let baseUrl = "" | |
enum Endpoint { | |
case login | |
case register | |
var endpoint: String { | |
switch self { | |
case .login: | |
return "login" | |
case .register: | |
return "register" | |
} | |
} | |
} | |
static func createUrl(endpoint: Endpoint) -> String { | |
return "\(API.baseUrl)\(endpoint.endpoint)" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Alamofire | |
protocol APIRequestRepresentable { | |
associatedtype CodableType: APIModelCodable | |
static var method: Alamofire.HTTPMethod { get set } | |
static var endpoint: API.Endpoint { get set } | |
static func request(parameters: Codable?, completion: @escaping (_ object: CodableType?, _ error: ErrorResponse?) -> Void) | |
static func defaultHeaderObject() -> DefaultHeader | |
static func defaultHeader() -> HTTPHeaders | |
static func tokenHeader(token: String) -> HTTPHeaders | |
static func url() -> String | |
} | |
extension APIRequestRepresentable { | |
static func defaultHeaderObject() -> DefaultHeader { | |
return DefaultHeader(contentType: "application/json; charset=utf-8", apiKey: API.apiKey) | |
} | |
static func defaultHeader() -> HTTPHeaders { | |
return defaultHeaderObject().asStringValueDictionary() | |
} | |
static func tokenHeader(token: String) -> HTTPHeaders { | |
return TokenHeader(defaultHeader: defaultHeaderObject(), token: "Bearer \(token)").asStringValueDictionary() | |
} | |
static func url() -> String { | |
return API.createUrl(endpoint: endpoint) | |
} | |
static func request(parameters: Codable?, completion: @escaping (_ object: CodableType?, _ error: ErrorResponse?) -> Void) { | |
AlamoHelper.manager.request( | |
url(), | |
method: method, | |
parameters: parameters?.asDictionary(), | |
encoding: JSONEncoding.default, | |
headers: defaultHeader()).responseJSON { response in | |
//each response should have a status code and a json value | |
guard let statusCode = response.response?.statusCode else { | |
completion(nil, ErrorResponse(reason: "Could not get status code")) | |
return | |
} | |
guard let jsonValue = response.result.value else { | |
completion(nil, ErrorResponse(reason: "Could not get JSON value")) | |
return | |
} | |
guard let data = try? JSONSerialization.data(withJSONObject: jsonValue) else { | |
completion(nil, ErrorResponse(reason: "Could not parse data")) | |
return | |
} | |
if 200...299 ~= statusCode { | |
//success | |
completion(CodableType.from(data: data), nil) | |
} else { | |
//error - we need a JSONDecoder here because `ErrorResponse` does not conform to APIModel | |
completion(nil, try? JSONDecoder().decode(ErrorResponse.self, from: data)) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Alamofire | |
import SwiftyJSON | |
struct LoginRequest: APIRequestRepresentable { | |
typealias CodableType = User | |
static var method: Alamofire.HTTPMethod = .post | |
static var endpoint: API.Endpoint = .login | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol APIModel { | |
var id: Int { get set } | |
} | |
typealias APIModelCodable = APIModel & Codable | |
extension APIModel where Self: Codable { | |
static func from(json: String, using encoding: String.Encoding = .utf8) -> Self? { | |
guard let data = json.data(using: encoding) else { return nil } | |
return from(data: data) | |
} | |
static func from(data: Data) -> Self? { | |
let decoder = JSONDecoder() | |
decoder.dateDecodingStrategy = .iso8601 | |
return try? decoder.decode(Self.self, from: data) | |
} | |
var jsonData: Data? { | |
let encoder = JSONEncoder() | |
encoder.dateEncodingStrategy = .iso8601 | |
return try? encoder.encode(self) | |
} | |
var jsonString: String? { | |
guard let data = self.jsonData else { return nil } | |
return String(data: data, encoding: .utf8) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct User: APIModelCodable { | |
var id: Int | |
var name: String | |
var email: String | |
var admin: Bool | |
var token: String | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class ViewController: UIViewController { | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
let loginRequest = Login(email: "[email protected]", password: "password") | |
LoginRequest.request(parameters: loginRequest) { (user, error) in | |
//`user` is of type `User` thanks to the typealias declaration in `LoginRequest` | |
} | |
} | |
} |
AlamoHelper and DefaultHeader are missing..
great gist , but like the others will search for the AlamoHelper idea
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How can this be adapted to return a collection of models? For example if you were to get all users for instance?