A Crash Course on Networking in iOS
The majority of apps require networking to connect to external services and data sources. ‘Networking’ means exchanging information via ‘http’ (Hypertext Transfer Protocol), one of the most used protocols. Every time you open your browser and retrieve or send data, you are using HTTP as the protocol. In this article you will learn how to work with networking in iOS by looking at the following options:
- HTTP
- Rest API
- NSURLSession: Networking without third party libraries
- Alamofire: Networking with a third party library to simplify the process
- A list of other networking libraries
If you are already familiar with the HTTP and REST APIs, skip to the NSURLSession
.
This article is part of a series of iOS related articles I am writing based on an application in development that will later be open sourced. The application makes use of data from Wikimedia Commons, and uses the site’s REST API to access this data.
HTTP
HTTP is one of the most popular protocols. If you are reading this article, you are using HTTP to retrieve the HTML page from the Sitepoint Servers. Your client (the browser) sends a request to the server and the server returns information about the requested resource(s). In the context of a mobile app, it will request lists of data, and the server responds with the requested data. These are called GET
requests.
Sometimes you have to post some data to the server from an app, for example an update. These are called POST
requests.
There are other types of requests (or verbs) as well, such as:
- GET
- POST
- HEAD
- PUT
- PATCH
If you’re interested in reading more about the HTTP protocol, I recommend this Wikipedia article.
REST API
A REST API is a simple and standard way to exchange data. You have some data on a server and want to retrieve it in an application. First you need to know how to structure your API, or ‘Application Programming Interface’ as the majority of APIs are a wrapper around a database.
As an example, you have a database table containing a list of books and your app needs to retrieve details on those books.
First you need a location to retrieve this data from. For this example, the domain is https://books.com/, and the API is at /api.
How should you represent your data on the API?
Data accessed through the API should be organized into collections and entities, in this case a collection is a group of books, represented as:
https://example.com/api/books
This url will return a collection of books. You can also implement pagination and search to this collection (https://example.com/api/v2/books?page=2
, https://example.com/api/v2/books?query='Jump Start PHP Environment'
). An entity is a specific book from the collection. It can be represented as https://example.com/api/v2/books/1
where 1
is an id.
Using the GET
, POST
and PUT
verbs from HTTP you can manipulate the entities and collections. Using the GET
verb, you can retrieve a book with an ID. For example, https://example.com/api/v2/books/7
. Using the POST
verb you can add a new book on the collection of books. You should also specify the required fields with other parameters.
Now you have a view of how to organize resources in an API, it’s time to decide how you will present the data. My favorite format is JSON as it helps two systems communicate in a manner that its not coupled with the language itself.
A JSON message might look like this:
{
"id": 7,
"userId": 20,
"title": "Jump Start PHP Environment",
"description": "Many entry level PHP developers want a quick path to glory, a shortcut to “knowing PHP.” Too many books and tutorials go straight into a pre-made, awful environment that just wants you to code, with no regard for security, version control, or other absolutely essential practices. This book is aimed at the absolute beginner who wants to start learning PHP, but aims to set you up with a thorough understanding of what makes for a good, modern, adaptable PHP environment before you start diving into PHP itself."
}
If your interested in building your own API I recommend this Sitepoint Article or if you are using WordPress and want to turn it into an API, this article.
NSURLSession
From iOS 7+ you can work with NSURLSession
for networking.
NSURLSession
is the ‘native’ way to work with remote data sets in Swift. Alamofire is built upon this technology. The following code is an example (Not production ready) of how to retrieve a login token from the Wikimedia Commons API.
class WCLoginApi {
static func nsurlAction(){
// Create a session configuration
let session = NSURLSession.sharedSession()
var stringUrl: String = "https://en.wikipedia.org/w/api.php"
stringUrl = stringUrl.stringByAppendingString("?action=query")
stringUrl = stringUrl.stringByAppendingString("&format=json")
stringUrl = stringUrl.stringByAppendingString("&meta=tokens")
stringUrl = stringUrl.stringByAppendingString("&type=login")
let url: NSURL = NSURL(string: stringUrl)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let task = session.dataTaskWithRequest(request) {
(
let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error")
return
}
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(dataString)
}
task.resume()
}
}
WCLoginApi.nsurlAction()
First you need session configuration, and in this example you retrieve the shared session configuration. This is a useful method if your app will repeatedly use the same general connection configuration, but not if you expect to make different requests.
After retrieving the configuration, you need to build the url and parameters. In this case the base url is https://en.wikipedia.org/w/api.php and the parameters are action
, format
, meta
and type
. GET
is used as the HTTP verb as you are retrieving a token from the server.
The creation of the task
to execute is the more complex part. After definition, the resume
method executes it asynchronously. When defining task
, a callback passed as an argument and print(dataString)
prints the data retrieved from the server.
Alamofire
Alamofire is an opinionated library that aims to make networking with iOS simpler. If you are planing to use more custom networking, for example using a different protocol, this library may not suit you. But if you are planing to use traditional REST APIs and simple networking, then I recommend trying Alamofire.
You can install Alamofire with CocoaPods, Carthage, or manually, so I recommend reading their installation guide for your preferred method.
Here is the earlier example re-written to use Alamofire:
import Alamofire
class WCLoginApi {
static func alamofireExample() -> Void
{
Alamofire.request(
.GET,
"https://en.wikipedia.org/w/api.php",
parameters: [
"action": "query",
"format": "json",
"meta": "tokens",
"type": "login"
]).responseJSON { response in
if let JSON = response.result.value {
if let loginTokenKey = JSON.objectForKey("query")?.objectForKey("tokens")?.objectForKey("logintoken") {
print(loginTokenKey)
}else{
print("Error to parse JSON")
}
}else{
print("Error with response")
}
}
}
}
WCLoginApi.alamofireExample()
To make a request you call the request
method that takes the HTTP verb as the second argument (these are a constants in Alamofire, .GET
in this case). The third argument is the base url without any arguments as a String
.
Next is a list of parameters (the same as in NSURLSession
). In this example you don’t encoded them as with the NSURLSession
‘s example, Alamofire builds them for you. You could build the url and parameter string yourself, but this is a better approach.
When dealing with Rest APIS, you will encounter different formats. The Wikimedia Commons API supports different formats, but as you know it will be in JSON, you can use the responseJSON
method. There are other call back methods for different formats.
I think this is simpler and more structured than the native iOS way. There are better ways to architect with the native method, but Alamofire makes it simpler. Alamofire isn’t limited to retrieving data but can also post and download data.
Alamofire allows you to change cache settings, check headers, chain responses (for example, checking the responseJSON
method with other response types), validate data from the response, authenticate users and more.
What Else?
Networking is a common task, so your options for simplifying the process are not limited to Alamofire. Here are some other libraries to consider:
- SwiftHTTP: A simple Swift wrapper around
NSURLSession
. - Moya: A Swift alternative to Alamofire.
- FSNetworking: Foursquare’s Objective-C networking implementation.
- Reach: A simple Swift library to check if you have network.
- iOS-netdiag: An Objective-C network diagnosis library.
In this article you learned the basics of iOS networking and REST Apis, the default iOS way to deal with networking, and Alamofire as an alternative.
As networking is a common task for every developer, I’d love to hear about your approach and what techniques or libraries have worked best for you.