Thoughts On AlamoFire

Swift’s AFNetworking Implementation


The HTTP protocol is synonymous with modern development. The experienced iOS developer understands and likely works with the popular protocol on a daily basis.

Unsurprisingly, iOS apps are no different in this regard. Thousands of apps and their engineers have trusted the popular AFNetworking library with everything from communicating with servers, parsing JSON, to providing place holder images while the intended ones are still being served up.

In short — it’s a tough act to follow. This week, we’ll look at the library intended to do just that: Alamofire.

The Basics

At its core, Alamofire seeks to simplify HTTP networking in iOS. It carries out its mission with incredible efficiency by harnessing NSURLSession and the Foundation URL Loading System to create a networking interface that feels native to swift.

Swift forgoes the delegate pattern and instead uses callbacks. I, for one, welcome this choice. While promise-based patterns can certainly help, they also hide certain code smells and are a little too magical for some.

Further, it’s built to be asynchronous. You might have heard, but performing networking calls on the main thread is a bad idea. Alamofire, thankfully, employs many best practices out of the box.

Caching, for example, is handled by NSURLCache which helps to prevent needless requests. In addition, if HTTP status codes are within acceptable ranges (200–299), one can also utilize its rich chaining model to do a significant amount of work in an insignificant amount of code.

History Repeats Itself

Alamofire also carries over some of the patterns that AFNetworking users will be familiar with, and some processes are far departures from its predecessor. This is mostly due to the fact that Alamofire is built to utilize all of swift’s niceties.

For instance, AFNetworking calls for a subclassed AFHTTPSessionManager for each API. There are exceptions to that rule, such as opting for NSURLConnection over NSURLSession.

Alamofire calls for a similar approach in that one creates a router by conforming to a protocol, URLRequestConvertible. Under the hood, Alamofire calls for a singleton pattern that’s built on top of an NSURLSessionConfiguration.

GET real

But hey, let’s start at the beginning:

Alamofire.request(.GET, “http://www.telize.com/jsonip?callback=getip").response {(request, response, data, error) in
println(request + response + error)
}

Like AFNetworking and other HTTP networking libraries, Alamofire provides easily accessible utility methods to make quick and dirty requests. This particular GET request will return a Request object which can be chained to perform all sorts of HTTP processes.

In Alamofire, the default behavior yields NSData accumulated from the server’s response. Here, I chained a response handler via a closure to parse the response, or — heaven forbid- respond to any errors that were birthed during the request.

Response

Responses manifest themselves in many different forms over HTTP. The most favored, though, is no doubt JSON. JSON, as you know, is XML’s younger, more athletic, baby brother.

Alamofire takes in JSON with opens arms and a hearty smile:

Alamofire.request(.GET, “http://httpbin.org/get").responseJSON {(request, response, JSON, error) in
println(JSON)
}

There are several responses one could specify from the simple strings to JSON.

Keep.Going()

Chaining is woven deep in the fabric of Alamofire. Those of yesteryear either smile or cringe when thinking of all the square brackets that one would type while message passing in Objective-C.

Swift, like most other modern languages, keeps the method invocations coming by way of a simple “.”. Alamofire can handle several response handlers, and each will execute asynchronously once the server sends off its response.

In keeping tradition, an example straight from the horse’s mouth:

Alamofire.request(.GET, “http://httpbin.org/get")
.authenticate(HTTPBasic: user, password: password)
.progress { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in
println(totalBytesRead)
}.responseJSON { (request, response, JSON, error) in
println(JSON)
}.responseString { (request, response, string, error) in
println(string)
}

Parameters

Of course, HTTP networking would be far less exciting without the ability to post data to a server or specify what one is querying for:

Alamofire.request(.GET, “http://httpbin.org/get", parameters: [“key”: “value”])

An inline dictionary is all that’s needed to include parameters in Alamofire. If you don’t specify any, nil will be tidily passed along. The same goes for encoding, which is the fourth argument in the request function.

Enums

If one has used swift in any capacity, they’ve likely witnessed how crazy and powerful swift’s enums are. Objective-C, even with the modern NS_ENUM, really only allowed for typedef integer declarations.

Swift has a few more tricks.

Alamofire embraces them in full, as all the logic for encoding parameters into an HTTP message is done with the ParameterEncoding enum. Further, all HTTP verbs as defined in RFC 2616 §9 are defined in one as well:

public enum Method: String
{
case OPTIONS = “OPTIONS”
case GET = “GET”
case HEAD = “HEAD”
case POST = “POST”
case PUT = “PUT”
case PATCH = “PATCH”
case DELETE = “DELETE”
case TRACE = “TRACE”
case CONNECT = “CONNECT”
}

By the way — if you are curious about all the wonders that swift enums are capable of, download my swift starter guide on the house. Pardon the plug.

Router

Creating a request router is the heart of the operation. Here, one will define the common endpoints that would be used with an API. Creating one is done via an enumeration which conforms to URLRequestConvertible.

When an enumeration conforms to URLRequestConvertible, it’s responsible for containing a variable called URLRequest. URLRequest must also be of type NSURLRequest.

Common practices to HTTP networking libraries occur here. One will most likely define a static string denoting a base URL and an API key/consumer secret.

Keep in mind that in the real world (which you most likely inhabit), it’s best to not keep those around in source code. I personally opt for .plist files.

In any event…

The workflow goes like this:

  • Define a base URL
  • Define your endpoints via case statements in an enumeration (i.e. Users, Comments, etcetera.)
  • URLRequest gets initialized and set up via a trailing closure. In the closure, parameters are added and the endpoint is constructed.
  • A URL, URLRequest, and encoding are all accounted for and a fully qualified request is issued to the server.

Read that a few times. At first, I thought it be a bit unruly — too many responsibilities tied to one function.

In practice, it works quite well:

The workflow looks like this:

enum APIRouter: URLRequestConvertible
{
static let BASE_URL = //base url
static let API_KEY = //api key, consumer secret for OAuth, etc

case User(Int)
case ProfilePicture(Int, Size)
case Likes(Int, Int)

var URLRequest: NSURLRequest
{
let (path: String, parameters: [String: AnyObject]) =
{
switch self
{
case .User (let page):
let params = []//Provide params
return (“/user”, params)
case .ProfilePicture(let id, let size):
var params = []
return (“/profilepictures/\(id)”, params)
case .Likes(let id, let commentsPage):
var params = []
return (“/likes/\(id)/user”, params)
}
}()

let URL = NSURL(string: APIRouter.BASE_URL)
let URLRequest = NSURLRequest(URL:URL!.URLByAppendingPathComponent(path))
let encoding = Alamofire.ParameterEncoding.URL
        return encoding.encode(URLRequest, parameters: parameters).0
}
}

A bit heavy handed for an example, but I opted to show what the code might look like out in the wild.

Feature Rich

Alamofire has many reasons to to convince the programmer to use it. Leveraging NSURLSession feels like the future of HTTP networking in iOS. It has a few checks in its column over NSURLConnection:

  • Background uploads and downloads
  • Ability to pause and resume network operations
  • Configurable container
  • Subclassable and private storage
  • Improved authentication handling
  • Perform authentication on an per connection basis
  • Rich delegate model — NSURLConnection has asynchronous block based methods, but a delegate can’t be used with them. NSURLSession has a hybrid approach.

I think we can agree it was the right choice. If one is curious what AFNetworking can do that Alamofire can’t, here you are:

  • UIKit extensions
  • TLS verification
  • Scenarios calling for NSOperation/NSURLConnection/AFURLConnectionOperation
  • Reachability
  • Multipart HTTP request construction

Depending on the scenario, these points are either game breakers or wholly unimportant.

Final Thoughts

At this point, there are several engineers who would argue that AFNetworking has become a fancy wrapper for the powerful NSURLSession. That may be true to some extent, but even so — is that such a bad thing?

It simplifies and abstracts very well, and though it doesn’t contain everything AFNetworking can do, it’s a promising start to HTTP networking in swift.

Thanks for reading, and I’ll see you next week for another .POST([“iOSBlog”:”TravelediOSDevelopersGuide”,”Author”:”@JordanMorgan10”).


Jordan Morgan is an iOS software engineer who runs Dreaming In Binary.
@jordanmorgan10.


If you learned something about AlamoFire, please NSRecommend this article below.