Show Menu

Looking for an iOS Developer?

Submit your 30 day Job Listing for FREE

In parts 1, 2, and 3 we went over some basics of Swift, and set up a simple example project that creates a Table View and a puts some API results from iTunes inside of them. If you haven’t read that yet, check out Part 1, Part 2, and Part 3.

This article is part of the create iOS8 Applications with Swift tutorial series, here are the other published articles:

    Make stuff happen!

    Okay, so first things first. There’s one more thing we need to clean up. The Table View Cell that is being created in the delegate function cellForRowAtIndexPath is not the most efficient way to create cells. In Objective-C we always wanted to use dequeueReusableCellWithIdentifier in order to get a cell out of memory if one is available, rather than creating a new one every time a cell is rendered. This helps make scrolling fast, and keeps the memory usage down.

    So, in our SearchResultsViewcontroller.swift file, we are going to replace the instantiation of the cell with the following:

    
    let kCellIdentifier: String = "SearchResultCell"
    var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as UITableViewCell
    if cell == nil {
       cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: kCellIdentifier)
    }
    

    What this is going to do is give us an already instantiated cell in the first line of Swift code. The second line checks to see if there was actually a cell set, and if not (if it’s nil), then we instantiate one as we did before. For some reason or another this swift code crashes if we don’t also specify the cell as a prototype cell in our storyboard, and set it’s reuse identifier to SearchResultCell. So open up your storyboard and select the tableview, change the number of ‘prototype cells’ to 1, and then click in to the cell. In the attributes inspector change the type to “Subtitle” and type in the identifier as “SearchResultCell”.

    Run the app! Once again, we have the exact same result, except this time it’s actually memory efficient and uses best practices!

    Making the cells ACTUALLY do something

    Okay, now we have one more delegate function that UITableView is going to call on our delegate class, SearchResultsViewController. This one will look like this:

    
    func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!)
    

    Whenever a cell is tapped, this function will run. So let’s grab out the iTunes data for the row that was clicked by accessing the index of the array set by indexPath.row, the integer id of the row clicked. And then let’s display the same info in a popup.

    Add your didSelectRowAtIndexPath method like so:

    
    func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
       // Get the row data for the selected row
       var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
    
       var name: String = rowData["trackName"] as String
       var formattedPrice: String = rowData["formattedPrice"] as String
    
       var alert: UIAlertView = UIAlertView()
       alert.title = name
       alert.message = formattedPrice
       alert.addButtonWithTitle("Ok")
       alert.show()
    }
    

    Here, we’re setting rowData to the value of whatever the array object at the selected index is to first get the information in to rowData. Then, we set the name and formattedPrice variables based on the rowData dictionary. Next, we instantiate an UIAlertView object, and set it’s title, message, and add a cancel button. Finally we show the alert with alert.show()

    Give it a run and you should now be able to see the name and price of any app clicked show up in a popup window. Cool right?

    Full iOS8 ViewController.swift code:

    
    //
    //  ViewController.swift
    //  TestSwift
    //
    //  Created by Jameson Quave on 6/2/14.
    //  Copyright (c) 2014 JQ Software LLC. All rights reserved.
    //
    
    import UIKit
     
    class SearchResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, APIControllerProtocol {
        
        let kCellIdentifier: String = "SearchResultCell"
        
        var api: APIController = APIController()
        @IBOutlet var appsTableView : UITableView
        var tableData: NSArray = NSArray()
                                
        override func viewDidLoad() {
            super.viewDidLoad()
            api.delegate = self
            UIApplication.sharedApplication().networkActivityIndicatorVisible = true
            api.searchItunesFor("Angry Birds");
        }
        
        func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
            return tableData.count
        }
        
        
        func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
            
            var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as UITableViewCell
            if cell == nil {
                cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: kCellIdentifier)
            }
            
            var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
            
            cell.text = rowData["trackName"] as String
            
            // Grab the artworkUrl60 key to get an image URL for the app's thumbnail
            var urlString: NSString = rowData["artworkUrl60"] as NSString
            var imgURL: NSURL = NSURL(string: urlString)
            
            // Download an NSData representation of the image at the URL
            var imgData: NSData = NSData(contentsOfURL: imgURL)
            cell.image = UIImage(data: imgData)
            
            // Get the formatted price string for display in the subtitle
            var formattedPrice: NSString = rowData["formattedPrice"] as NSString
    
            cell.detailTextLabel.text = formattedPrice
            
            return cell
        }
        
        func didRecieveAPIResults(results: NSDictionary) {
            // Store the results in our table data array
            if results.count>0 {
                self.tableData = results["results"] as NSArray
                self.appsTableView.reloadData()
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
            }
        }
        
        func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
            
            // Get the row data for the selected row
            var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
            println(rowData)
            
            var name: String = rowData["trackName"] as String
            var formattedPrice: String = rowData["formattedPrice"] as String
            
            var alert: UIAlertView = UIAlertView()
            alert.title = name
            alert.message = formattedPrice
            alert.addButtonWithTitle("Ok")
            alert.show()
            
        }
        
    }
    
    

    having issues?

    We have a Questions and Answer section where you can ask your iOS Development questions to thousands of iOS Developers.

    Ask Question

    FREE Download!

    Get your FREE Swift 2 Cheat Sheet and quick reference guide PDF download when you sign up to SwiftMonthly


    Sharing is caring

    If you enjoyed this tutorial, please help us and others by sharing using one of the social media buttons below.


    Written by:

    I am an app developer in Austin, TX. I spend time dabbling with iPhone, iPad, Android, and web technologies. I write about technology, startups, and my technology & entrepreneurial experiments. More of my Swift Tutorials can be found on my site.

    Comments

    comments