Mobile Development

Networking APIs

Communicating to remote APIs is a common occurance for mobile applications. You can rely on centralized servers for user authentication and content generation into your app. Facebook uses an API to authenticate you, retrieve your news feed, pictures, comments and perform actions such as generating a new friend request.

Apple provides a set of classes for connecting to remote URLs including APIs. That collection is centered around NSURLSession.

Definitions

As in previous chapters, let's frame our discussion with terms and classes used in this chapter:

  • JSON - JavaScript Object Notation - A readable text format used to communicate simple objects such as strings and integers.
  • NSURLConnection - A class that lets you load the contents of a URL by providing a URL request object. [2]
  • NSURLRequest - Represents a URL load request in a manner independent of protocol and URL scheme. [3]
  • NSURLSession - Provides an API for downloading content via HTTP. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads. [1]
  • SSL - Secure Sockets Layer, a protocol for securing a connection between two endpoints which allows for encrypted transmissions.

Code Examples

The two most common examples of talking to an external server are downloading a file as well as GET and POST commands.

Downloading a file

The following code will download an image file from Wikipedia and once downloaded, will return that file within the response closure:

import UIKit
import XCPlayground // Specific for Playgrounds

XCPSetExecutionShouldContinueIndefinitely() // Allows us to run asynchronous code in Playgrounds

let url = NSURL(string: "http://en.wikipedia.org/wiki/File:Cuernos_del_Paine_from_Lake_Peho%C3%A9.jpg")!

var session = NSURLSession.sharedSession()
let requestTask = session.dataTaskWithRequest(NSURLRequest(URL: url), completionHandler: { (data, response, error) -> Void in
    NSLog("response from our request was \(response)")
})

NSLog("Going to begin downloading the file")
requestTask.resume()

And the above console output is:

2015-01-11 17:24:04.005 MyPlayground2[82717:16247271] Going to begin downloading the file
2015-01-11 17:24:04.214 MyPlayground2[82717:16247321] response from our request was <NSHTTPURLResponse: 0x7fae92007760> { URL: http://en.wikipedia.org/wiki/File:Cuernos_del_Paine_from_Lake_Peho

Please note that when downloading larger files, we can start looking at NSURLSession delegates to manage resuming downloads should a failure occur.


Primarily, we will be working with GET and POST to web services. The following code demonstrates these two commands

GET

The following code will submit a GET to Google for querying the term Swift. The code will then output the result to the console.

Note that query parameters are added into the HTTPAdditionalHeaders.

import Foundation
import XCPlayground // Specific for Playgrounds

XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) // Allows us to run asynchronous code in Playgrounds

let parameters = Dictionary(dictionaryLiteral: ("q", "swift"))
var config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.HTTPAdditionalHeaders = parameters

var session:NSURLSession = NSURLSession(configuration: config)
let url = NSURL(string: "http://google.com")!

let task = session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
    if error != nil {
        print("Error trying to GET from Google \(error)")
    }
    else {
        var result = NSString(data: data, encoding:
            NSASCIIStringEncoding)!
        print("We retrieved the data as \(result)")
    }
})
task.resume()

POST

POST is different than GET in that the data is not sent in the URL but is instead sent as a separate payload, and is typically JSON.

In the below example, we are going to be posting a JSON string and outputting the result to the console.

import XCPlayground // Specific for Playgrounds

XCPSetExecutionShouldContinueIndefinitely() // Allows us to run asynchronous code in Playgrounds

let url = NSURL(string: "http://your-post-url-here")! // make sure to put a valid URL!
let jsonString = "{'test':12345}"
var urlRequest = NSMutableURLRequest(URL: url)
urlRequest.HTTPMethod = "POST"
urlRequest.HTTPBody = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)

var session = NSURLSession.sharedSession()

let requestTask = session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) -> Void in
    if error != nil {
        print("we had an error \(error)")
    }
    else {
        var result = NSString(data: data, encoding:
            NSASCIIStringEncoding)!
        print("response from our request was \(result)")
    }
})

print("Going to begin POSTing")
requestTask.resume()

The APIs that you'll be connecting to will provide direction on proper endpoints and expected data payloads as well as expected response data for both success and failure conditions.

[Advanced] HTTPS and SSL

The majority of API connections should be requiring an SSL connection. SSL encrypts the data between the phone and the server, which makes it difficult for hackers to eavesdrop on the data being exchanged.

NSURLSession has delegate methods, namely didReceiveChallenge that can be implemented to handle SSL connections correctly. Please see the following blog post for more details:

https://medium.com/swift-programming/learn-nsurlsession-using-swift-ebd80205f87c

Reference

Learn NSURLSession with Swift - https://medium.com/swift-programming/learn-nsurlsession-using-swift-ebd80205f87c

iOS NSURLSession with Swift - http://hayageek.com/ios-nsurlsession-example/

[1] NSURLSession Class Reference https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSession_class/

[2] NSURLConnection Class Reference https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/index.html

[3] NSURLRequest Class Reference https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/