Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@vani2
Last active May 26, 2020 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vani2/a82f490c81441ba33ae3f01369a5c73d to your computer and use it in GitHub Desktop.
Save vani2/a82f490c81441ba33ae3f01369a5c73d to your computer and use it in GitHub Desktop.
// Services Layer
final class EntityService: APIService, EntityServiceProtocol {
typealias EntityCompletion = (Result<Entity, Error>) -> Void
@discardableResult
func createEntity(_ entity: Entity, completion: @escaping EntityCompletion) -> Progress {
let endpoint = CreateEntityEndpoint(entity: entity)
return apiClient.request(endpoint, completionHandler: completion)
}
}
// APIClient Library
public final class Client {
public func request<T>(_ endpoint: T, completionHandler: @escaping (Result<T.Content>) -> Void) -> Progress where T: Endpoint {
let anyRequest = AnyRequest(create: endpoint.makeRequest)
// Alamofire Session Manager
let request = sessionManager.request(anyRequest).responseData { (response: DataResponse<Data>) in
let result = APIResult<T.Content>(catching: { () throws -> T.Content in
let data = try response.result.unwrap()
return try endpoint.content(from: response.response, with: data)
})
// outside can log errors remotely to analytics service or our own backend API
self?.responseObserver?(response.request, response.response, response.data, result.error)
completionHandler(result)
}
return progress(for: request)
}
}
class BaseEndpoint {
var encoder: JSONEncoder { return JSONEncoder.default }
public func content(from response: URLResponse?, with body: Data) throws -> Content {
try responseValidator.validate(response, with: body)
let resource = try JSONDecoder.default.decode(ResponseData<Root>.self, from: body)
return content(from: resource.data)
}
}
class ResponseValidator {
internal func validate(_ response: URLResponse?, with body: Data) throws {
try validateAPIResponse(response, with: body)
try validateHTTPStatus(response)
}
private func validateAPIResponse(_ response: URLResponse?, with body: Data) throws {
//throws ResponseError or APIError
}
private func validateHTTPStatus(_ response: URLResponse?) throws {
//throws HTTPError
}
}
// Presentation Layer
final class EntityViewController: UIViewController, ErrorPresentable {
private let entityService: EntityServiceProtocol
func createNewEntity(_ entity: Entity) {
startLoading()
entityService.createEntity(entity) { [weak self] (result: Result<Entity, Error>) in
guard let self = self else { return }
self.stopLoading()
switch result {
case .success(let newInterKey):
// do business
case .failure(let error):
self.showError(error)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment