Skip to content

Instantly share code, notes, and snippets.

@ykpoh
Created July 18, 2021 11:51
Show Gist options
  • Save ykpoh/be58bf541b893fef9c8a877492661255 to your computer and use it in GitHub Desktop.
Save ykpoh/be58bf541b893fef9c8a877492661255 to your computer and use it in GitHub Desktop.
import Alamofire
protocol APIServiceProtocol { // 1
func fetchLaunchesWithQuery(startDate: Date, endDate: Date, completion: @escaping (LaunchResponse?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol
func fetchRocket(rocketName: String, completion: @escaping (Rocket?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol
}
extension APIServiceProtocol { // 2
@discardableResult func fetchLaunchesWithQuery(startDate: Date = Calendar.current.date(byAdding: .year, value: -3, to: Date()) ?? Date(), endDate: Date = Date(), completion: @escaping (LaunchResponse?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol {
return fetchLaunchesWithQuery(startDate: startDate, endDate: endDate, completion: completion)
}
@discardableResult func fetchRocket(rocketName: String, completion: @escaping (Rocket?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol {
return fetchRocket(rocketName: rocketName, completion: completion)
}
}
class APIService: APIServiceProtocol { // 3
let baseUrlString: String
var sessionManager: SessionProtocol
// 4
init(baseUrlString: String = "https://api.spacexdata.com/v4", sessionManager: SessionProtocol = AF) {
self.baseUrlString = baseUrlString
self.sessionManager = sessionManager
}
// 5
@discardableResult func fetchLaunchesWithQuery(startDate: Date, endDate: Date, completion: @escaping (LaunchResponse?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol {
let parameters = [
"query": [
"date_utc": [
"$gte": DateFormatter.iso8601Full.string(from: startDate),
"$lte": DateFormatter.iso8601Full.string(from: endDate)
]
],
"options": [
"sort": [
"utc_date": "asc"
],
"pagination": false
]
]
let postLaunchesQueryEndpoint = "\(baseUrlString)/launches/query"
let method: HTTPMethod = .post
let headers: HTTPHeaders? = nil
return sessionManager.request(postLaunchesQueryEndpoint, method: method, parameters: parameters, encoding: method == .get ? URLEncoding.default : JSONEncoding.default, headers: headers)
.responseJSON { dataResponse in
guard let data = dataResponse.data else { return }
let decoder = JSONDecoder()
do {
let launches = try decoder.decode(LaunchResponse.self, from: data)
completion(launches, nil, dataResponse)
} catch {
completion(nil, error, dataResponse)
}
}
}
// 6
@discardableResult func fetchRocket(rocketName: String, completion: @escaping (Rocket?, Error?, AFDataResponse<Any>) -> Void) -> DataRequestProtocol {
let postLaunchesQueryEndpoint = "\(baseUrlString)/rockets/\(rocketName)"
return sessionManager.request(postLaunchesQueryEndpoint, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil)
.responseJSON { dataResponse in
guard let data = dataResponse.data else { return }
let decoder = JSONDecoder()
do {
let rocket = try decoder.decode(Rocket.self, from: data)
completion(rocket, nil, dataResponse)
} catch {
completion(nil, error, dataResponse)
}
}
}
}
// 7
protocol SessionProtocol {
func request(_ convertible: URLConvertible,
method: HTTPMethod,
parameters: Parameters?,
encoding: ParameterEncoding,
headers: HTTPHeaders?) -> DataRequestProtocol
}
protocol DataRequestProtocol {
func responseJSON(completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self
}
extension Alamofire.Session: SessionProtocol {
func request(_ convertible: URLConvertible, method: HTTPMethod, parameters: Parameters?, encoding: ParameterEncoding, headers: HTTPHeaders?) -> DataRequestProtocol {
return request(convertible, method: method, parameters: parameters, encoding: encoding, headers: headers, interceptor: nil, requestModifier: nil)
}
}
extension DataRequest: DataRequestProtocol {
func responseJSON(completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self {
return responseJSON(queue: .main, dataPreprocessor: JSONResponseSerializer.defaultDataPreprocessor, emptyResponseCodes: JSONResponseSerializer.defaultEmptyResponseCodes, emptyRequestMethods: JSONResponseSerializer.defaultEmptyRequestMethods, options: .allowFragments, completionHandler: completionHandler)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment