Skip to content

Instantly share code, notes, and snippets.

@rxmichael
Last active September 1, 2017 01:40
Show Gist options
  • Save rxmichael/948252a2560a00a100cc8d31f5f8a3ca to your computer and use it in GitHub Desktop.
Save rxmichael/948252a2560a00a100cc8d31f5f8a3ca to your computer and use it in GitHub Desktop.
Robots and Pencils

To the best of my abiliity I tried to approach this problem in an efficient and reusable pattern. Also while making use of Swift 4's new Codable and Decodable protocols.

To maximize code reusability for both RPComment and RPAnnotation, have them both inherit the Prodcut class (which I will then use in the NetworkManager to leverage the same call for both objects.

Also the NetworkManager blueprint can be used for different types of store (Parse, REST API)

I used Alamofire for simplcity purposes.

What I am trying to maximise is a reusable design pattern to save code duplication and isolation for further changes.

/**
This is an example of a REST API Network Manager. We have implemented the retreive method to work via an HTTP GET request to the API
Alamofire is used for simplicity of showing the request
**/
import Foundation
import Alamofire
class APIManager: NetworkManagaer {
static let sharedInstance = APIManager()
fileprivate init() {}
func retreive(id: String, completion: @escaping ServiceResponse)
{
let finalEndPoint = "example endpoint"+id
Alamofire.request(finalEndPoint).validate().responseJSON() { response in
switch response.result {
case .success:
if let value = response.result.value {
let decoder = JSONDecoder()
let product = try decoder.decode(Product.self, from: data)
completion(product, nil)
}
case .failure(let error):
completion(nil, error)
}
}
}
}
/**
This class represents the blueprint of a Network manager, it has a retreving function that will be overriden depending on the use of Parse
or REST API
**/
import Foundation
import Alamofire
typealias ServiceResponse = ((Product?, Error?) -> Void)
class NetworkManager {
static let sharedInstance = NetworkManager()
fileprivate init() {}
func retrieve(id: String, completion: @escaping ServiceResponse) {}
}
import Foundation
class Product: Codable {
/**
This class is the blueprint of RPComment and RPAnnotation, it conforms the Codable protcol to allow JSON encoding and decoding.
and will be used to leverage the same retreival/saving function for both an RPComment and RPAnnotation
**/
}
import Foundation
class RPAnnotation: Product {
let name: String
let id: Int
let message: String
init(name: String, id: Int, message: String) {
self.name = name
self.id = id
self.message = message
}
enum RPAnnotationKeys: String, CodingKey { // keys name for the JSON enconding
case name = "name"
case id = "id"
case message = "message"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: RPAnnotationKeys.self) // defining our container
let name: String = try container.decode(String.self, forKey: .name) // extract the data at our keys
let id: Int = try container.decode(Int.self, forKey: .id)
let message: String = try container.decode(String.self, forKey: .message)
self.init(name: name, id: id, message: message) // initizialize the class
}
}
import Foundation
class RPComment: Product {
let author: String
let id: Int
let content: String
init(author: String, id: Int, content: String) {
self.author = author
self.id = id
self.content = content
}
enum RPCommentKeys: String, CodingKey { // keys name for the JSON enconding
case author = "author"
case id = "id"
case content = "content"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: RPCommentKeys.self) // defining our container
let author: String = try container.decode(String.self, forKey: .author) // extract the data at our keys
let id: Int = try container.decode(Int.self, forKey: .id)
let content: String = try container.decode(String.self, forKey: .content)
self.init(author: author, id: id, content: content) // initizialize the class
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment