Networking in Swift: Building the Swift Client, Part 5

This is the final article in our tutorial segment on building a Swift client application to query a RESTful API and serve the response to the end user in a table view. If you've been following along since the introductory article, we've come a long way, and we're almost done! But we're not at our final destination just yet.

When we last left off in part four, we had added the necessary code to display thumbnail images next to our lists of inventory items. In this article, we will walk through the process of adding views for each individual item in our inventory such that when a user taps an item in the list view, she'll be presented with an item description scene that displays: 1) a bigger picture of the item, 2) the name of the item, and 3) the lengthy item description provided by the API. Let's jump right in.

The Item Description Scene
We will now set up our final story board scene. When the user taps on an inventory item from among those listed in the table view, we want to display a new view that provides an image at the top of the screen and below it a scrollable content area that displays the description text for the selected item. Create a new file,  and name it PlumbingSupplyItemDescriptionViewController:

Switch over to the main storyboard and drag a view controller into the scene. Next, drag in an Image View and place it to the top of newly added view controller. Give the Image View a height of 160 points using the size inspector in the utilities panel. With the Image View selected, bring up the 'pin' popover view as shown below:

Within the 'pin' view, uncheck the 'Constrain to margins' box and select the horizontal red bars and the top vertical red bar. Also check the 'Height' box as shown below:

Finally, click the button that reads 'Add 4 Constraints.' If done correctly, you should see no red or yellow lines near the Image View:

Now drag and drop a Text View into the scene, and size it as shown below with a small margin all around. (The vibrant color you see in the image below on the Text View was set by us so that it is clear what object we are referring to).

While the Text View is selected, bring up the 'pin' menu again, uncheck the 'Constrain to margins' box, and select the horizontal red bars and the vertical red bars as shown below, and then add the constraints:

We will now make the view controller that we dragged into our storyboard be of type PlumbingSupplyItemDescriptionViewController. Ensure that the view controller is selected. From the Identity Inspector menu locate the Class field and type in PlumbingSupplyItemDescriptionViewController as shown here:

Open the Assistant Editor. You should now see the main storyboard with our selected view controller along with the corresponding class. To the top of this class add the following code:

Like so:

To link these IBOutlets (@IBOutlet) to the elements to our main storyboard, we select the given element on the story board with [control+left mouse button] and drag the blue line over to the corresponding variable as shown below:

Do this for both elements in the view controller (i.e. the image and the text), connecting them to the corresponding outlets in the class.

When we select a table view cell from our list of inventory items, we want our newly-added view controller to be presented to the user. To do this we will [control+left mouse button] from the table view cell located in each of our table view controllers and drag the blue line over to the new view controller. Do this for both table view controllers. When the drop down menu appears select 'Show.'

From Apple Docs: “The Navigation Bar provides a control for navigating hierarchical content. It’s a bar, typically displayed at the top of the screen, containing buttons for navigating within a hierarchy of screens." To prevent the Navigation Bar from overlapping our Image View, we need to set some properties in the main storyboard. Ensure that the newly-added view controller is selected. From the Attributes Inspector menu locate the check box labeled 'Under Top Bars' and uncheck it. Run the application, navigate to one of the two categories and select one of the item table view cell. You should see a view similar to the following:

Item Description Scene: Displaying Image and Text
When using storyboards with segues, the system provides a callback method to the source view controller for when the segue is about to be performed. This allows us to prepare the destination view controller for its presentation onto the screen. (A segue is triggered when we select a table view cell that was linked to some view controller using a storyboard segue.) Ensure that the callback method is located in the PlumbingSupplyInventoryTableViewController class like so (by default it is supplied in the class but commented out):

Uncomment this code block if it is commented out, and replace the comments in this callback method with the following snippet:

On the first line, the segue object provides a reference to the destination view controller. On the second line we cast the sender object that the callback method provides as a table view cell since the cell that was selected becomes the sender of this segue event. Then we grab the index of the selected cell, on line three, and use it to retrieve the associated plumbing supply item from our data source and send it over to the destination view controller on line four. To avoid having to download the image again we simply capture it in our destination view controller from the selected table view cell.

Now back to the destination view controller class, a.k.a the PlumbingSupplyItemDescriptionViewController. Define these three functions:

The viewDidAppear(animated: Bool) function is a system method that we override with custom behavior after the view appears onto the screen. In this method we set the title of the view controller to the name of the selected item and call a function that downloads the description of an item. Replace the comment, '// title and download //,' within this method with the following snippet:

Notice that the item description text is passed through a completion handler closure once the download is complete. The code 'self.bsn_textView.text = itemDescription' sets the Text View's text area with the text of the item description. On the source view controller, we did not use this completion handler, which is available on its networking request method, but instead made the UI updates inside the method itself. We prefer to update the UI outside of the method that is tasked to download content as it makes for clearer code by breaking up the variegated logic into separate sections. Both approaches are possible, as we'll now see.

In the function urlForItemWithDescription(itemID : String) -> (NSURL?) add the following lines of code:

This method takes an item's id, maps it one of two possible endpoints and inserts that item id into the selected endpoint. The mapping is done by inspecting the first two characters of an item's id and using a switch statement.

In the function, requestItem(endPointURL : NSURL?, responseHandler : (. . .) -> () ) -> (), add the following code:

This code should look familiar. We already described what this code does when we originally downloaded inventory items. The only difference here is that we passed our data for the UI element to the completion block.

For our final function, i.e. the system function viewDidLoad(), place the following code within it:

The first line of code takes the captured image that was assigned to us by the source view controller and insert it into our Image View. The second line sets the font type and size of the items description. The third line disables editing of the Text View since this functionality should not be applicable. The fourth line displays text that serves to indicate that there is activity with getting an items description. Run the application and navigate to the item description page. You should see a screen similar to the one depicted below:

Success!  With that, we've completed the last major task for our Super PHPlumbing Bros Swift client application! When run, the client queries our custom API to first display the titles of the two inventory categories supplied by the API. When the user selects one of those categories, the app displays a list view of the inventory and provides each item's name along with the corresponding thumbnail image. And finally, when the user selects an individual item, the app displays the full image along with the item's full description.

This project can be found on GitHub.

We hope you've found this tutorial series helpful and fun. As always, questions, comments and suggestions are welcome below!

Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5

This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 

No comments:

Post a Comment