There’s a New iOS Networking Library on the Block

Tyler Milner
Atlas
Published in
3 min readJan 2, 2018

As any iOS developer knows, networking is an essential part of any mobile app. When Apple introduced URLSession in iOS 7, the community embraced it with open arms. The new APIs were a great improvement over the older URLConnection APIs. At Bottle Rocket, we’re always trying to seek a balance between efficiency and maintainability when we build apps for our clients. For this reason, we would often write our networking code from scratch, building on top of URLSession directly. This was great from a maintainability standpoint — keeping our networking code in-sync with Apple’s SDKs was extremely easy. However, as we’ve grown, we realized that there is often some common boilerplate networking code that must be written over and over again. Rather than turn to a third party solution, many of which are extremely heavy, we decided to write our own.

Say Hello to Hyperspace

We recently open sourced Hyperspace on GitHub under the Apache 2.0 license. When we built Hyperspace, we had a few goals in mind:

  • Reduce the amount of HTTP boilerplate that you need to write by hand. This includes things like defining HTTP methods, status codes, and headers.
  • Keep things lightweight — make it easy and convenient to handle 90% of networking use cases out of the box. This includes specifying the model type you wish to get back from a request so that it can automatically be parsed using the magic of Swift 4’s Codable protocol.
  • Keep things simple — we want to make it easy for anyone to contribute. The entire library is around 600 SLOC.

Usage Example

Add Hyperspace to Your Project

Once you add Hyperspace to your project, you’ll be up and running in no time. Simply add Hyperspace to your Podfile (support for other dependency managers will be added soon):

pod 'Hyperspace'

Define Network Requests

Defining a request is simple. Simply create an instance of AnyNetworkRequest<T> and specify your request parameters:

let someRequest = 
AnyNetworkRequest<Model>(method: .post,
url: URL(string: "...")!,
headers: [.contentType: .applicationJSON],
body: postBody)

Notice that Model refers to the success model response type for your request. This means that if your request’s response type conforms to Decodable, we’ll automatically handle the decoding for you.

Also notice that the method and headers parameters rely on predefined types. No more “stringly typed” APIs that are prone to typos!

Execute Network Requests

It’s the job of a BackendService to execute your network requests. Simply create a BackendService and then call its execute() method:

let backendService = BackendService()backendService.execute(request: someRequest) { (result) in
switch result {
case .success(let responseObject):
// Request successful
case .failure(let error):
// Request failed
}
}

Upon completion of the request, you will get back a result enum that contains your parsed Model if the request succeeded or an Error if the request failed. This is nice because you don’t have to deal with unwrapping optionals in your caller code. You also don’t have to handle “impossible” code paths like getting back a nil result object and nil error at the same time, which is one of my personal annoyances with the (Data?, URLResponse?, Error?) completion block type of URLSession’s dataTask(withRequest:completionHandler:).

Conclusion

I hope I’ve piqued your interest with this short article. It really is that easy to start making type-safe network requests, so if you’re looking for a networking solution in your next project, give Hyperspace a try. Whether you end up using it or not, we’d love for you to let us know what you think!

--

--