Skip to content

Instantly share code, notes, and snippets.

@cmoulton
Created November 16, 2016 16:02
Show Gist options
  • Save cmoulton/733356fd0a29411153155606c0cdc2ba to your computer and use it in GitHub Desktop.
Save cmoulton/733356fd0a29411153155606c0cdc2ba to your computer and use it in GitHub Desktop.
Demo code for Strongly-Typed GET and POST Calls With Alamofire at https://grokswift.com/strongly-typed-api-calls/. Uses Swift 3.0 and Alamofire 4.0.
import Foundation
import Alamofire
enum BackendError: Error {
case objectSerialization(reason: String)
}
extension Todo {
class func endpointForID(_ id: Int) -> String {
return "https://jsonplaceholder.typicode.com/todos/\(id)"
}
class func endpointForTodos() -> String {
return "https://jsonplaceholder.typicode.com/todos/"
}
convenience init?(json: [String: Any]) {
guard let title = json["title"] as? String,
let userId = json["userId"] as? Int,
let completed = json["completed"] as? Bool
else {
return nil
}
let idValue = json["id"] as? Int
self.init(title: title, id: idValue, userId: userId, completedStatus: completed)
}
func toJSON() -> [String: Any] {
var json = [String: Any]()
json["title"] = title
if let id = id {
json["id"] = id
}
json["userId"] = userId
json["completed"] = completed
return json
}
class func todoByID(_ id: Int, completionHandler: @escaping (Result<Todo>) -> Void) {
Alamofire.request(Todo.endpointForID(id))
.responseJSON { response in
let result = Todo.todoFromResponse(response: response)
completionHandler(result)
}
}
func save(completionHandler: @escaping (Result<Todo>) -> Void) {
let fields = self.toJSON()
Alamofire.request(Todo.endpointForTodos(),
method: .post,
parameters: fields,
encoding: JSONEncoding.default,
headers: nil)
.responseJSON { response in
let result = Todo.todoFromResponse(response: response)
completionHandler(result)
}
}
private class func todoFromResponse(response: DataResponse<Any>) -> Result<Todo> {
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print(response.result.error!)
return .failure(response.result.error!)
}
// make sure we got JSON and it's a dictionary
guard let json = response.result.value as? [String: Any] else {
print("didn't get todo object as JSON from API")
return .failure(BackendError.objectSerialization(reason:
"Did not get JSON dictionary in response"))
}
// turn JSON in to Todo object
guard let todo = Todo(json: json) else {
return .failure(BackendError.objectSerialization(reason:
"Could not create Todo object from JSON"))
}
return .success(todo)
}
}
import Foundation
class Todo {
var title: String
var id: Int?
var userId: Int
var completed: Bool
required init?(title: String, id: Int?, userId: Int, completedStatus: Bool) {
self.title = title
self.id = id
self.userId = userId
self.completed = completedStatus
}
func description() -> String {
return "ID: \(self.id), " +
"User ID: \(self.userId), " +
"Title: \(self.title)\n" +
"Completed: \(self.completed)\n"
}
}
import UIKit
class ViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// MARK: Get Todo #1
Todo.todoByID(1) { result in
if let error = result.error {
// got an error in getting the data, need to handle it
print("error calling POST on /todos/")
print(error)
return
}
guard let todo = result.value else {
print("error calling POST on /todos/ - result is nil")
return
}
// success!
print(todo.description())
print(todo.title)
}
// MARK: Create new todo
guard let newTodo = Todo(title: "My first todo",
id: nil,
userId: 1,
completedStatus: true) else {
print("error: newTodo isn't a Todo")
return
}
newTodo.save { result in
guard result.error == nil else {
// got an error in getting the data, need to handle it
print("error calling POST on /todos/")
print(result.error!)
return
}
guard let todo = result.value else {
print("error calling POST on /todos/. result is nil")
return
}
// success!
print(todo.description())
print(todo.title)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment