Tutorial details

Developing iOS Apps Using Swift Tutorial | App Code for Sale | Preview

Developing iOS Apps Using Swift Tutorial - Part 2 | iOS Tutorial

How to hit the iTunes Search API for the iTunes Store, download the JSON results, parse them in to Dictionaries and then populate our Table View with this information, add some user interaction by adding a click event to the tableview.

Overview PAGE TOP

In Part 1 we went over some basics of Swift, and set up a simple example project that creates a Table View and a puts some text inside of them. If you haven’t read that yet, give it a read here.

For this section, we’re going to do something a little more ambitious. We’re going to hit the iTunes Search API for the iTunes Store, download the JSON results, parse them in to Dictionaries and then populate our Table View with this information. Then, we will add some user interaction by adding a click event to the tableview, so that when an item is clicked the iTunes store item will be opened.

If this sounds like a lot of work, don’t sweat it. This is pretty basic functionality for iOS apps and it’s one of the most common things any developer has to do. Let’s get going…

Connecting the UI PAGE TOP

The first thing we need to do is get a reference to our tableView, so it can be used from code. Go ahead and add this line to your ViewController.swift file, just under the class definition, but outside of any functions.

@IBOutlet var appsTableView : UITableView

This bit of code allows up to connect our Table View in our Storyboard to this variable, “appsTableView”. Save this file and open up your storyboard. Now by control+click+dragging from the Table View to our ‘View Controller’ object, we’ve linked these objects. Easy, right?

Making the API Request PAGE TOP

Now that we have the UI connected, we’re ready to make an API call. Create a new function called searchItunesFor(searchTerm: String). We’ll use this to make our requests happen for arbitrary search terms.

To keep this tutorial short, I’m going to just post my final code and let the comments do some of the explaining. I’m always open to questions and further discussion in the comments though, so feel free to chime in!

   func searchItunesFor(searchTerm: String) {

   // The iTunes API wants multiple terms separated by + symbols, so replace spaces with + signs

   var itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)

&nbsp; &nbsp;// Now escape anything else that isn't URL-friendly<br />&nbsp; &nbsp;var escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)<br />&nbsp; &nbsp;var urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=software"<br />&nbsp; &nbsp;var url: NSURL = NSURL(string: urlPath)<br />&nbsp; &nbsp;var request: NSURLRequest = NSURLRequest(URL: url)<br />&nbsp; &nbsp;var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)

&nbsp; &nbsp;println("Search iTunes API at URL \(url)")

&nbsp; &nbsp;connection.start()<br />}

Let’s go line-by-line.

First, we need to do some fixing of the search terms we pass in, the Search API wants terms in the form of “First+Second+Third+Words” rather than “First%20Second%20…” etc. So instead of URL-encoding, we use an NSString method called stringByReplacingOccurencesOfString. This returns a modified versions of the searchTerm variable with all our spaces replaced with + symbols.

Next, we actually escape the search term in case of an other symbols that won’t fit in a URL.

The next 2 lines define an NSURL object that can be used as a Request URL for iOS’s networking API.

These two lines are critical:

var request: NSURLRequest = NSURLRequest(URL: url)

var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)

The first creates an NSURLRequest object with our target URL being the url variable we created above. The second line then creates the *connection* which is going to be used to actually send the request. Notice in the parameters we set the delegate to self. This allows us to listen in on resultant information coming from the connection inside of our View Controller class.

Finally, connection.start() actually begins the request.

Preparing for the response PAGE TOP

Now we’ve got a method that starts an iTunes search response when we call it. So let’s insert the following at the end of viewDidLoad…

searchItunesFor("JQ Software")

This will find any software products on the iTunes store containing that phrase, which in this case will include a couple of games I made years ago, and a few more recent things. Feel free to change the search string to whatever you like.

Now to actually recieve the response we need to keep track of a data object which will contain the results. So first let’s add an instance of NSMutableData as a member of our class, do this by inserting the following line just below the class definition, inside of the curly braces. While we’re at it, let’s also create an array to hold our table info.

var data: NSMutableData = NSMutableData()<br />var tableData: NSArray = NSArray()

Now, let’s incorporate the functions that NSURLConnection will be sending our class, since it is the delegate of our request we can expect any information from NSURLConnection to be sent back through it’s protocol methods, defined in NSURLConnectionDataDelegate and NSURLConnectionDelegate. If you don’t know what that means, that’s okay. Let’s just proceed and you’ll see how it works.

Recieving the response PAGE TOP

Now we’re going to add the biggest chunk of code so far, which is still not much code, to handle the entirety of the resulting information:

func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {<br />&nbsp; &nbsp;// Recieved a new request, clear out the data object<br />&nbsp; &nbsp;self.data = NSMutableData()<br />}

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {<br />&nbsp; &nbsp;// Append the recieved chunk of data to our data object<br />&nbsp; &nbsp;self.data.appendData(data)<br />}

func connectionDidFinishLoading(connection: NSURLConnection!) {<br />&nbsp; &nbsp;// Request complete, self.data should now hold the resulting info<br />&nbsp; &nbsp;// Convert the retrieved data in to an object through JSON deserialization<br />&nbsp; &nbsp;var err: NSError<br />&nbsp; &nbsp;var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options:&nbsp;NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

&nbsp; &nbsp;if jsonResult.count>0 && jsonResult["results"].count>0 {<br />&nbsp; &nbsp; &nbsp; var results: NSArray = jsonResult["results"] as NSArray<br />&nbsp; &nbsp; &nbsp; self.tableData = results<br />&nbsp; &nbsp; &nbsp; self.appsTableView.reloadData()

&nbsp; &nbsp;}<br />}

When NSURLConnection receives a response, we can expect the didReceiveResponse method to be called on our behalf. At this point we simply reset our data by saying self.data = NSMutableData(), creating a new empty Data object.

After a connection is made, we will start recieving data in the method didReceiveData. The data argument being passed in here is where all our juicy information comes from. We need to hold on to each chunk that comes in, so we append it to the self.data object we cleared out earlier.

Finally when the connection is done and all data has been recieved, connectionDidFinishLoading is called and we’re ready to use the data in our app. Hooray!

The connectionDidFinishLoading method here uses the NSJSONSerialization class to convert our raw data in to useful Dictionary objects by deserializing the results from iTunes.

Now, because we know the rough layout of the data coming back from iTunes, a simple check on the count of the “results” key is enough to validate that we did in fact get back the data we were expecting, so we can now set our self.tableData object to be the resulting data, and tell the appsTableView to reload it’s content. This will cause the Table View object to run it’s own delegate methods. Defining these is the final step in our tutorial.

Updating the Table View UI PAGE TOP

You may remember from last time we implemented two function for our Table View. A count function, which determines the number of rows; and a cell function, which actually creates the cell and modifies it for each row.

We’re going to update these now to use the data we pulled down from the web.

Swap out your methods with these two functions:

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {<br />&nbsp; &nbsp;return tableData.count<br />}

&nbsp; &nbsp;func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {<br />&nbsp; &nbsp;let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")

&nbsp; &nbsp;var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary

&nbsp; &nbsp;cell.text = rowData["trackName"] as String

&nbsp; &nbsp;// Grab the artworkUrl60 key to get an image URL for the app's thumbnail<br />&nbsp; &nbsp;var urlString: NSString = rowData["artworkUrl60"] as NSString<br />&nbsp; &nbsp;var imgURL: NSURL = NSURL(string: urlString)

&nbsp; &nbsp;// Download an NSData representation of the image at the URL<br />&nbsp; &nbsp;var imgData: NSData = NSData(contentsOfURL: imgURL)<br />&nbsp; &nbsp;cell.image = UIImage(data: imgData)

&nbsp; &nbsp;// Get the formatted price string for display in the subtitle<br />&nbsp; &nbsp;var formattedPrice: NSString = rowData["formattedPrice"] as NSString

&nbsp; &nbsp;cell.detailTextLabel.text = formattedPrice

&nbsp; &nbsp;return cell<br />}

The numberOfRowsInSection is now simply returning the number of resultant objects from the tableData member, which is set in our prior connectionDidFinishLoading method.

The cellForRowAtIndexPath is also not changed dramatically in this case. Rather than simply returning the row number, we use the row number to grab three pieces of information: the track name, the artwork url, and the price.

Using these keys we construct the title, subtitle, and an image to go along with the cell.

Try running our app, and you’ll see we for the first time have created something that actually looks like an app all in Swift!

The final code for this part of the tutorial can be found here.

But, why is it so laggy!? PAGE TOP

In this tableview, we’re not properly handling quite a few things. Over the next 3 sections we’ll dive in to what that means and what the proper changes we need to make are. If you like, jump ahead to part 5 where these issues are resolved.

Next time in Part 3 we’ll work on the interaction piece of the app, allowing users to search for anything they like, and making the table cells clickable!

Reference PAGE TOP


0 Comments Leave a comment

Please login in order to leave a comment.

Newest first

to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.