Swift — Write Concise Networking Code with WS☁️
In this article, we are going to go through step by step, what is required to get User
objects from a JSON Api in Swift3, using the ☁️ws library.
What is ws ?
ws is a swift library for writing concise networking code.
ws leverages the power of other libraries to make networking a breeze. Under the hood, it uses the great Alamofire for HTTP Requests, 🎬then for the popular Promise Concept and 🏹Arrow for the simple JSON Parsing.
This architechture is modular on purpose so that every “brick” doe_s_ one thing and does it well.
If you wish to go deeper into the inner-workings of ws , you can checkout :
- Alamofire on github
- JSON Parsing with 🏹Arrow and its related article
- Promises with 🎬then and its related article
Let’s get some JSON back, shall we?
Installation
If you want to follow this tutrial on Xcode, make sure to create a new iOS project and install ws as explained here, both Carthage and Cocoapods are supported
Disabling App Transport Security (ATS)
Here we will use the great JSONPlaceholder service to get some JSON users https://jsonplaceholder.typicode.com/users
In order to be able to process requests to this domain, we need to bypass App Transport Security settings in our .plist
file like so :
⚠️ B_are in mind that this ATS setting is for testing purpose and not meant to be in a production App _
Crafting our Api
Start by creating a new Swift file named Api.swift
, this will encapsulate all of our api specific code:
import ws
import then // Needed to import Promise Type
import Arrow // Needed to import JSON Type
let api = Api() // Define global api
struct Api {
// Connect to the base URL
private let ws = WS("http://jsonplaceholder.typicode.com")
// Declare your route and what you want back, here some JSON
func getUsers() -> Promise<JSON> {
return ws.get("/users")
}
}
And now you can call your api from a view controller like this:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
api.getUsers().then { json in
print(json)
}
}
}
Wow that was easy wasn’t it?
Yeah but most of the time, in your apps, you’ll want to use custom Swift models. Alright so now we’re going to see next how we translate the JSON into our nice User.swift
model.
Set up Model Parsing
Create a User.swift
file and add a username property.
struct User {
var username = ""
}
Create a User+JSON.swift
file and map the JSON key to your model property:
import Arrow
extension User: ArrowParsable {
mutating func deserialize(_ json: JSON) {
username <-- json["username"]
}
}
That’s all that’s needed to describe how to parse a User
object for now.
Now modify the previous Api.swift
file and make the getUsers() function returns Promise<[User]>
instead of JSON.
import ws
import then
let api = Api()
struct Api {
private let ws = WS("http://jsonplaceholder.typicode.com")
func getUsers() -> Promise<[User]> { // We want [User] back!
return ws.get("/users")
}
}
Yes! That’s the only thing to change! Now ws will automatically try to parse the response into an array of User
objects 🎉!
Let’s use it in our controller then!
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
api.getUsers().then { users in
for u in users {
print(u.username)
}
}
}
}
Bonus — Handle errors
As you know, things don’t always work as we intend and we need to prepare ourselves for the worst. So what if the request fails for instance?
That’s where the power of promises comes in :
api.getUsers().then { users in
// strongly typed [User] !
}.onError { e in
print(e) // Handle any networking error that might happen
}.finally {
print("Whatever happens I'll be executed ")
}
Just chain an .onError
block in there and it will be called with the corresponding reason whenever something wrong happens!
Conclusion
With roughly 20 lines of code you have :
- Connected to a distant JSON Api
- Got JSON back
- Parsed JSON into your models
- A way to handle failures when the worst happens
It’s as concise as it gets I guess
Of course there is much more ws can do : handle params, nested models, POST, PUT, DELETE request, multipart uploads, progress, Loadmore requests… But this is out of the scope of this article.
More goodness ❤️
☁️ws is part of a series of lightweight libraries aiming to make developing iOS Apps a breeze. At freshOS we thrive for simple apis, so go checkout our repos and happy coding
Special thanks to maxkonovalov and Yanickdot for proofreading
If you liked this article press the heart ❤ below that means a lot to us !
Originally published here