Asynchronous Data Handling with Swift

It is near impossible today if you are writing a mobile app and not retrieving data from the Internet as JSON from a REST API compliant service. To make this easy there are a lot of libraries that are available for you to use like Almofire, AFNetworking and then even more invovled projects that map your JSON data to your class. These can be one of EKMapping or Mantle to name a few (commonly used ones). What if you did not want to use libraries that have a whole lot of files and code that could be daunting for a simple task?

Getting Data from a REST API

Firstly we need a URL from where we shall get the REST data. For this example we shall get data from http://httpbin.org/ip if you open this in a browser, it returns data back to us which looks something like
{
  "origin": "10.201.160.136"
}
You would get different results than the ones shown here as it will be different at your end.

How to get data using Swift

you need to set up a url using NSURL and then create a task from this URL to download data.
let url = NSURL(string:"http://httpbin.org/ip")
 let session = NSURLSession.sharedSession()
 let task = session.dataTaskWithURL(url!){
    data, response, error in
    print("Done")
 }
 task.resume()

When you run this code, you will notice the slight delay and when it does complete, it prints Done to the console. The handler takes three parameters, namely data, response and error.

Converting the JSON data into String

The function above retrieves JSON in NSData format and we need to convert this into a string before we can view it.

if let JSONString = NSString(data: data!, encoding: NSUTF8StringEncoding) {
        print(JSONString)
    }

Parsing JSON

We can parse JSON better when it is in it's original format of Array or Dictionary than in String format. The JSON serialization functions allow us to unserialize NSData into JSON which we can use. IN this particular case, the return value is a dictionary which we shall parse.

do {
        let values = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
        if let theDict = values as? [String:AnyObject], let value = theDict["origin"] {
            print("origin = \(value)")
        }    
    } catch {
        print("Error")
    }

Notes

You could also use Dictionary instead of [String:AnyObject]. You can iterate through the values and even set the values to a user class/structure.

The parsing can be a bit more complicated and that is where a lot of external libraries come in handy. However getting and parsing simple data is not difficult either.

If you want to run this code in Playgrounds, you can but you will need to do a couple of things. First you need to import XCPlayground library. The second thing that you need to do is set the playgrounds to execute indefinitely so that it can handle asynchronous calls by setting the XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

Comments

Popular Posts