How to make REST API calls & parse JSON with Swift 2.0
Transcript – How to make REST API calls & parse JSON with Swift 2.0
Hey everyone! Pulling a random stat out of thin air, I’d say 90% of web APIs are REST APIs. Don’t quote me on the percent, like I said, I made it up. The point is, there’s alot of data behind REST APIs and we need to know how to connect our iOS apps to get that data. In this tutorial, we’re going to write Swift code to perform a GET and a POST request.
REST overview
If you’re not familiar with REST, here’s the quick 30 second cliff note version. REST is an architectural style for creating a web service that almost always works over HTTP. It works pretty much works the same way as getting web pages, but you also have standard methods to create, update and delete. If your computer can do web, it can do REST. That’s why everyone is using it. Since we’re doing GET and POST, that means we are focusing on read and create.
To make our REST calls, we’re going to use a few online testing servers. We’ll use httpbin.org and requestb.in. Building a REST server is out of scope for this tutorial. We’ll cover that in other lessons, with other languages.
REST GET request in Swift
Let’s take a look at some code. The complete code is on GitHub.
// This makes the GET call to httpbin.org. It simply gets the IP address and displays it on the screen. func updateIP() { // Setup the session to make REST GET call. Notice the URL is https NOT http!! let postEndpoint: String = "https://httpbin.org/ip" let session = NSURLSession.sharedSession() let url = NSURL(string: postEndpoint)! // Make the POST call and handle it in a completion handler session.dataTaskWithURL(url, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in // Make sure we get an OK response guard let realResponse = response as? NSHTTPURLResponse where realResponse.statusCode == 200 else { print("Not a 200 response") return } // Read the JSON do { if let ipString = NSString(data:data!, encoding: NSUTF8StringEncoding) { // Print what we got from the call print(ipString) // Parse the JSON to get the IP let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary let origin = jsonDictionary["origin"] as! String // Update the label self.performSelectorOnMainThread("updateIPLabel:", withObject: origin, waitUntilDone: false) } } catch { print("bad things happened") } }).resume() }
In order to make a GET REST call using Swift, we first need a URL for our GET call. The URL we’ll use is https://httpbin.org with the path /ip. This URL represents the resource we’re trying to GET. In our case, we’re asking the REST service for our IP address. Behind the scenes, the REST service will read it out of our request and return it as JSON.
The next thing we need is an instance of NSURLSession. This is the object we’re using to make the REST request. It has a method called dataTaskWithURL that takes the URL we created and a completion handler. The method returns a task, which we call resume on. The completion handler contains our code that is run when we get a result. We get back the data, a response, and hopefully nothing in the error. In our handler, we’ll just unpack the data into JSON, which we’ll convert into a Dictionary, which we populate into a label. Since this code is in a completion handler, which is a different thread, we perform a selector to update the label. All done.
We should test the response code in our completion handler to make sure we got a response. If we get an HTTP status code of 200, that means we should have data in the response body. Otherwise something happened, and we need to account for it. I’m only testing for 200, but we could write special code for 404s, or my favorite 418.
Beware the App Transport Security error
Ok, one last thing I wanted to note was the url we used for the GET was https. That wasn’t an accident. In iOS 9, all our REST requests should be over https. If they are not, iOS will throw an App Transport Security error since our request is in clear text. To get around that, we can create a temporary exception in our info.plist. Apple uses the word temporary in the exception message, so I’m taking that to mean we can do it for now but who knows how long.
Here’s how we create an exception. Right click on the info.plist file for our application, and open it as source code. Instead of getting the plist editor, we’ll get the plist file as XML.
We need to add a key, and a dictionary for the key. Ultimately the exception we’re adding contains the domain name for the exception, and sub keys and dictionaries for specific flags like allowing insecure HTTP loads, minimum TLS, and if we should include subdomains. Don’t include http part for the domain name. In our case, it’s just requestb.in. You want to add this code somewhere under the main dict element for the plist. This will allow you to make REST calls to HTTP servers that are not encrypted.
REST POST in Swift
So let’s POST some data. To POST data, we set things up the same way. We need an endpoint URL, an NSURLSession, and an array of key-value pairs to post as JSON. I’m just using a simple array with the key as hello, and the value as Hello POST world.
Once we have those, we need to build a request object using the NSMutableURLRequest class. We set the method as the string POST. We also need to create a header variable for our request that tells the other server what we’re sending in the body of our message. In this example, we’re using JSON.
func postDataToURL() { // Setup the session to make REST POST call let postEndpoint: String = "http://requestb.in/r4jz64r4" let url = NSURL(string: postEndpoint)! let session = NSURLSession.sharedSession() let postParams : [String: AnyObject] = ["hello": "Hello POST world"] // Create the request let request = NSMutableURLRequest(URL: url) request.HTTPMethod = "POST" request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") do { request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(postParams, options: NSJSONWritingOptions()) print(postParams) } catch { print("bad things happened") } // Make the POST call and handle it in a completion handler session.dataTaskWithRequest(request, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in // Make sure we get an OK response guard let realResponse = response as? NSHTTPURLResponse where realResponse.statusCode == 200 else { print("Not a 200 response") return } // Read the JSON if let postString = NSString(data:data!, encoding: NSUTF8StringEncoding) as? String { // Print what we got from the call print("POST: " + postString) self.performSelectorOnMainThread("updatePostLabel:", withObject: postString, waitUntilDone: false) } }).resume() }
To make the request, we’ll use a different call on the session object. We’ll use dataTaskWithRequest. Instead of passing the URL, we’ll pass a request object. The request object has the URL when we created it. We call it the same way as before with a completion handler to perform any actions after we POST the request.
Now this server just responds with the word “ok” and the status code 200. To see what the server received, we can go to the URL for requestb.in. There we’ll see our request, and any other requests we recently made. The data is ephemeral, so don’t expect it to be there more than a few minutes.
Conclusion
So we’ve seen how to perform GETs and POSTs. We’ve also looked at how we add exceptions if our REST server is blocked for using insecure resource loads. The complete source code is available on GitHub. The link is in the description.
Thanks for watching! If you have any questions let me know in the comments. I try to get new videos out every week, so make sure you subscribe. You don’t want to miss a video! One side note before I go, the DeegeU.com website is down for upgrades over the next week. Videos will still be posted here.
And with that, I’ll see you in the next tutorial!
<!-- DeegeU - Right Side -->
<ins class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-5305511207032009" data-ad-slot="5596823779"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
Tools Used
- XCode
Media Credits
All media created and owned by DJ Spiess unless listed below.
- Teapot image from pixabay.com licensed under CC0
Easy Jam by Kevin MacLeod is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Source: http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100245
Artist: http://incompetech.com/
Get the code
The source code for “How to make REST API calls & parse JSON with Swift 2.0” can be found on Github. If you have Git installed on your system, you can clone the repository by issuing the following command:
git clone https://github.com/deege/deegeu-swift-rest-example.git
Go to the Support > Getting the Code page for more help.
If you find any errors in the code, feel free to let me know or issue a pull request in Git.
Comments
DJ Spiess
Your personal instructor
My name is DJ Spiess and I’m a developer with a Masters degree in Computer Science working in Colorado, USA. I primarily work with Java server applications. I started programming as a kid in the 1980s, and I’ve programmed professionally since 1996. My main focus are REST APIs, large-scale data, and mobile development. The last six years I’ve worked on large National Science Foundation projects. You can read more about my development experience on my LinkedIn account.