Skip to content

Instantly share code, notes, and snippets.

@shrawan2015
Last active February 16, 2018 12:25
Show Gist options
  • Save shrawan2015/89b75dbf09ed468854653c555a860556 to your computer and use it in GitHub Desktop.
Save shrawan2015/89b75dbf09ed468854653c555a860556 to your computer and use it in GitHub Desktop.
Reference @marcexmachina
https://gist.github.com/marcexmachina/ab2f613e5208279b20194926a76dd511
protocol APIClient {
var session: URLSession { get }
func fetch<T: Decodable>(with url: URL, completion: @escaping (Result<T>) -> Void)
}
extension APIClient {
var session: URLSession {
return URLSession(configuration: .default)
}
func fetch<T: Decodable>(with url: URL, completion: @escaping (Result<T>) -> Void) {
let task = session.dataTask(with: url) { (data, response, error) in
// Run on main thread
DispatchQueue.main.async {
guard error == nil else {
completion(.failure(APIError.requestFailed))
return
}
// Did we get a successful status code
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, 200..<300 ~= statusCode else {
// Handle status code
return
}
guard let data = data else {
return
}
do {
let model = try JSONDecoder().decode(T.self, from: data)
completion(.success(model))
} catch {
completion(.failure(APIError.jsonDecodingFailed))
}
}
}
task.resume()
}
}
struct LocationClient: APIClient {
private enum Path: String {
case locations = "/ios-code-test/v2/locations.json"
case location = "/ios-code-test/v2/location"
}
private func urlBuilder(for path: Path, id: Int? = nil) -> URL? {
var urlComponents = URLComponents(string: Constants.Endpoints.baseURL)
switch path {
case .locations:
urlComponents?.path = path.rawValue
case .location:
guard let id = id else {
return nil
}
urlComponents?.path = "\(path.rawValue)/\(id).json"
}
return urlComponents?.url
}
/// Method to retrieve list of `Location`s from API
///
/// - Parameter completion: completion handler
func fetchLocations(completion: @escaping (Result<[Location]>) -> Void) {
guard let url = urlBuilder(for: .locations) else {
return
}
fetch(with: url, completion: completion)
}
func fetchLocationDetails(for id: Int, completion: @escaping (Result<LocationDetails>) -> Void) {
guard let url = urlBuilder(for: .location, id: id) else {
return
}
fetch(with: url, completion: completion)
}
}
import UIKit
extension MuppetCellView {
struct Factory {
static func titleLabel() -> UILabel {
let titleLabel = UILabel(frame: .zero)
titleLabel.textAlignment = .center
titleLabel.numberOfLines = 0
titleLabel.font = UIFont.boldSystemFont(ofSize: 14)
return titleLabel
}
static func thumbnailImageView() -> UIImageView {
let thumbnailImageView = UIImageView(frame: .zero)
thumbnailImageView.contentMode = .scaleAspectFit
return thumbnailImageView
}
static func abstractLabel() -> UILabel {
let abstractLabel = UILabel(frame: .zero)
abstractLabel.textAlignment = .left
abstractLabel.numberOfLines = 0
abstractLabel.font = UIFont.systemFont(ofSize: 12)
return abstractLabel
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment