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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@IBOutlet weak var bsn_imageView: UIImageView! | |
@IBOutlet weak var bsn_textView: UITextView! | |
var bsn_plumbingItem: PlumbingSupplyItem? | |
var bsn_capturedImage: UIImage? | |
var urlSession = NSURLSession.sharedSession() | |
let backgroundQueue : dispatch_queue_t = dispatch_queue_create("com.aGupieWare.SwiftNetworking.backgroundQueue", nil) |
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):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let destViewController = segue.destinationViewController as PlumbingSupplyItemDescriptionViewController | |
let selectedCell = sender as UITableViewCell | |
let selectedIndex = self.tableView.indexPathForCell(selectedCell) | |
destViewController.bsn_plumbingItem = self.dataSource[selectedIndex!.row] | |
destViewController.bsn_capturedImage = selectedCell.imageView.image |
Now back to the destination view controller class, a.k.a the PlumbingSupplyItemDescriptionViewController. Define these three functions:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override func viewDidAppear(animated: Bool) { | |
super.viewDidAppear(animated) | |
// title and download // | |
} | |
// MARK: - Ancillary Methods | |
func urlForItemWithDescription(itemID : String) -> (NSURL?) { | |
// request endpoint for item // | |
} | |
// MARK: - Networking | |
func requestItem(endPointURL : NSURL?, responseHandler : (error : NSError? , itemDescription : String?) -> () ) -> () { | |
// request item description // | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.title = self.bsn_plumbingItem!.bsn_name | |
let url : NSURL? = self.urlForItemWithDescription(self.bsn_plumbingItem!.bsn_id!) | |
self.requestItem(url, responseHandler: { (error, itemDescription) -> () in | |
self.bsn_textView.text = itemDescription | |
}) |
In the function urlForItemWithDescription(itemID : String) -> (NSURL?) add the following lines of code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// extract the first two characters of an item's id // | |
let rangeOfHello = Range(start: itemID.startIndex, end: advance(itemID.startIndex, 2)) | |
let prefixItemID = itemID.substringWithRange(rangeOfHello) | |
var url : NSURL? | |
switch prefixItemID | |
{ | |
case "PT": | |
let filePath : String = "http://localhost:8888/api/v1/plumbing_tools/\(itemID).json" | |
url = NSURL(string: filePath) | |
case "CP": | |
let filePath : String = "http://localhost:8888/api/v1/copper_pipes_and_fittings/\(itemID).json" | |
url = NSURL(string: filePath) | |
default: | |
url = NSURL(string: "") | |
} | |
return url; |
In the function, requestItem(endPointURL : NSURL?, responseHandler : (. . .) -> () ) -> (), add the following code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let task = self.urlSession.dataTaskWithURL(endPointURL!, completionHandler: { (data, response, error) -> Void in | |
// convert the JSON response data into a NSDictionary // | |
var jsonParseError: NSError? | |
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonParseError) | |
as NSDictionary | |
var rawInventoryItems = jsonResult["data"] as Dictionary<String,String> | |
dispatch_async(dispatch_get_main_queue()!, { () -> Void in | |
// call our completion handler // | |
responseHandler( error: nil, itemDescription: rawInventoryItems["description"]) | |
}) | |
}) | |
task.resume() |
For our final function, i.e. the system function viewDidLoad(), place the following code within it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.bsn_imageView.image = self.bsn_capturedImage | |
self.bsn_textView.font = UIFont(name: "Helvetica", size: 22) | |
self.bsn_textView.editable = false | |
self.bsn_textView.text = "Loading. . ." |
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.
We hope you've found this tutorial series helpful and fun. As always, questions, comments and suggestions are welcome below!
Index
Introduction
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.
Source:http://blog.agupieware.com/2014/11/networking-in-swift-building-swift_17.html
Tidak ada komentar:
Posting Komentar