Skip to content

Jameson Quave

Using computer technology to educate, and improve lives.

Menu
  • Home
  • Contact
Menu

Developing iOS Apps Using Swift Part 4 – Adding Interactions

Posted on June 3, 2014April 16, 2015 by Jameson Quave

This section completely updated to reflect changes in Xcode 6.3, as of April 16, 2015

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. If you enjoy these tutorials, I’m also working on a book full of quality content for Swift developers, and it’s available for Pre-Order now.

Loading cells from a storyboard prototype

Okay, so first there is one more thing we need to clean up. The Table View Cell thats being created in the delegate function cellForRowAtIndexPath is not the most efficient way to create cells. In iOS we always want 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.

First, we are going to be referring to this cell by a storyboard prototype, which in code is represented by a string.
So, near the top of the SearchResultsViewController class, add the following line:

let kCellIdentifier: String = "SearchResultCell"

Next, we need to do some more storyboard modifications.
In order for Swift to know what a SearchResultCell is, we need to 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.

Next, we need to click the newly added prototype cell to select it in the attributes editor panel.
After you’ve selected it, in the attributes inspector change the Style to “Subtitle” and type in the identifier as “SearchResultCell”.

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

let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as! UITableViewCell

What this is going to do is give us an already instantiated cell.

Run the app, and once again we have the exact same result, except now we’re loading the cell from a storyboard prototype, which allows us to do all sorts of cool stuff with it.

Making the cells 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
    if let rowData = self.tableData[indexPath.row] as? NSDictionary,
        // Get the name of the track for this row
        name = rowData["trackName"] as? String,
        // Get the price of the track on this row
        formattedPrice = rowData["formattedPrice"] as? String {
            let alert = UIAlertController(title: name, message: formattedPrice, preferredStyle: .Alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
            self.presentViewController(alert, animated: true, completion: nil)
    }
}

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 UIAlertController object, and set it’s title, message, and add an “Ok” button to dismiss the alert. Finally we show the alert with self.presentViewController()

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?

The full code for Part 4 is available here.
Part 5 focuses on speeding up our Table View. To get updates on this tutorial in your email, subscribe here.

Go to Part 5 Now ->

30 thoughts on “Developing iOS Apps Using Swift Part 4 – Adding Interactions”

  1. Felix says:
    June 4, 2014 at 5:39 am

    Hi Jameson,
    first of all: great job! i actually now understand how to program iOS. It’s just because of this language & your tutorial.
    I tried to implement your snippets into my app, but for some reason, it shows nothing. HTTP JSON is OK, but i guess it hangs because i don’t have some identifier for my JSON. On iTunes,
    it is:
    {{“resultCount”:50, “results”: [ {Stuff1}, {Stuff2}]}
    But on mine, it is
    [{Stuff1},{Stuff2}]
    It stops on
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

    Do you have any idea, how i can fix that? I’d really would like to thank you!

    Reply
    1. Jameson Quave says:
      June 4, 2014 at 8:47 am

      I’m not sure that’s actually JSON in your case. If it does accept it for deserialization, it would be of type NSArray, and there would be no keys to read, just strings.

      Reply
  2. Mark says:
    June 4, 2014 at 12:49 pm

    for IB newbies like me who are bound to be very literal

    ‘In the attributes inspector change the type to “Subtitle”’

    replace ‘type’ with ‘Style’

    Reply
  3. Brandon says:
    June 4, 2014 at 2:50 pm

    Hey James,

    Since we’re using storyboards and prototype cells, isn’t it the case that the cell will never be nil?

    https://stackoverflow.com/questions/10254951/uitableview-cells-not-nil-at-initialization (reference the answer referencing storyboards).

    Reply
    1. Jameson Quave says:
      June 4, 2014 at 2:58 pm

      Yep, I actually removed it in the later parts, but didn’t remove it from here.

      Reply
  4. Kingiol says:
    June 6, 2014 at 1:55 am

    Hi,
    when use tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as? UITableViewCell method, should follow the link site
    http://stackoverflow.com/questions/24022763/uitableview-in-swift,
    otherwise,app crash

    Reply
  5. Tetsuo says:
    June 6, 2014 at 6:41 pm

    Why don’t you use type inference?

    Reply
    1. Jameson Quave says:
      June 6, 2014 at 6:58 pm

      Because I’m used to objective-c. No reason I can’t use it more, just a habit. This series will evolve to be more and more Swifty over time 🙂

      Reply
  6. David Ethell says:
    June 9, 2014 at 1:24 pm

    I’m getting fatal error: Can’t unwrap Optional.None on this line:

    cell.detailTextLabel.text = formattedPrice

    Reply
    1. Jameson Quave says:
      June 9, 2014 at 5:33 pm

      Remove that line, then add:
      println(cell.detailTextLabel)
      See if you get the same error. If not, then add
      println(formattedPrice)

      One of these two variable is effectively nil for one reason or another. First we need to know which one it is.

      Reply
    2. Rian Rainey says:
      June 16, 2014 at 7:56 am

      David – I had the same problem as you and couldn’t figure out what I was doing wrong. Eventually, in my Main.storyboard, I set the Table View Cell style from Custom to Subtitle. That made it work for me. Strange. Hope this helps.

      Reply
      1. Jameson Quave says:
        June 16, 2014 at 8:03 am

        Interesting, mine works fine set to Custom. I think this might just be the quirkiness of the beta. I would expect some of these issues to resolve themselves with the full release.

        Reply
  7. PeterO says:
    June 21, 2014 at 6:07 am

    Hi Jameson,
    have started to try SWIFT with your series. Thank you! A minute ago I have preordered your book.
    Could you please say something about the use of standard methods in Swift Could be it is very easy, but I do not see it.
    Example: I want to use the function from UITextKit to get the selected text in a text view as a string. I have the UITextRange value, but I cannot manage to declare/use the “func textInRange” in the correct way.

    In the Apple documents I see these lines:

    Return the text in the specified range. (required)
    Declaration
    SWIFT
    func textInRange(_ range: UITextRange!) -> String!
    OBJECTIVE-C
    – (NSString *)textInRangeUITextRange *)range

    Under “class ViewController” I have simply entered this line:

    func textInRange(_ range: UITextRange!) -> String!

    But I am getting the warning: “Extraneous ‘_’ in parameter: ‘range’ has no keyword argument name

    var textRange = myTextField.selectedTextRange
    println(textRange)
    The UITextKitTextRange output is correct, the selected text starts at 4 and is 9 characters long = (4, 9)B

    I am searching for example for 3 days now, but nothing about Swift, all about Objective-C.

    best regards
    Peter

    Reply
    1. Jameson Quave says:
      June 21, 2014 at 12:09 pm

      Hi Peter, the underscore means the parameter name is not required, as does the error message you’re seeing.
      Just use this:

      textInRange(textRange)

      Reply
      1. PeterO says:
        June 22, 2014 at 2:14 am

        Thank you Jameson,
        good to know what the underscore means.

        Meanwhile I have created the same code lines in objective-C and posted the question in macrumour forum. User “Dranix” has then given the Swift equivalent. It was very similar, but I had not found it.
        🙂
        Peter

        Swift -Code:
        mySelectedText2 = myTextField.textInRange(myTextField.selectedTextRange)

        Objective-C-Code:
        mySelectedText2 = [myTextField textInRange:(myTextField.selectedTextRange)];

        Reply
  8. Israel M. Bravo says:
    July 28, 2014 at 5:37 pm

    Hi Jameson

    The sample in this part 4 runs nice !!!

    But, every time I clicked the OK button in the message alert when the app display the row selected, in the console I received a warning with this message:

    2014-07-28 18:32:11.302 FirstApp[3201:141889] Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!

    Is this normal?

    Regards

    Israel

    Reply
    1. z4r says:
      July 29, 2014 at 7:38 am

      Same warning here 😐

      It seems to be a ßug: https://twitter.com/steipete/status/489847881248288770

      Reply
      1. Jameson Quave says:
        July 29, 2014 at 7:39 am

        This usually means you’re dismissing something twice, but I would assume it is in fact a bug in the beta.

        Reply
        1. Israel M. Bravo says:
          July 29, 2014 at 9:48 am

          Ok … thanks z4r & Jameson … will wait for the final release.

          Reply
  9. Matheus Kerkhoff says:
    December 9, 2014 at 10:28 am

    Hi, first of all, congratulations on the tutorials…they’ve been very helpful…. 🙂

    I just completed the 4th tutorial and Im having a small bug which I can’t figure out….

    Everytime I tap (click) the row in the tableview, it opens the second last item selected, it doesn’t show the item Im actually tapping on, but instead, the other I clicked before…the first I time I tap, nothing happens…

    Reply
    1. Jameson Quave says:
      December 10, 2014 at 3:24 am

      That’s strange, can you post it on github so I can take a look?

      Reply
    2. RobRob Boyd says:
      February 7, 2015 at 10:21 am

      Hi Matheus,

      I had the same problem as you. I’m guessing you used the function autocomplete and selected the wrong function (as I did). Make sure you have implemented didSelectRowAtIndexPath and not didDeselectRowAtIndexPath.

      Reply
      1. Marc says:
        June 1, 2015 at 12:53 pm

        Thank you!

        Reply
      2. jon says:
        July 18, 2015 at 6:15 pm

        Great call – I did the exact same thing!

        Reply
    3. Jason says:
      February 7, 2015 at 11:25 am

      Same thing was happening to me. I accidentally imported the didDeselectRowAtIndexPath instead of the didSelectRowAtIndexPath!

      Reply
  10. Austin says:
    February 23, 2015 at 6:18 pm

    The frustrating part for me is that most of the code of the code goes unexplained. How would I know what key value pair would return the price from the itunes appstore? Sure I can go google the API, but it would make sense to include that in this tutorial. Just my .02, but I feel a lot is missing.

    Reply
    1. Jameson Quave says:
      February 24, 2015 at 9:06 am

      Log the JSON to the console and look for yourself.

      Reply
      1. Austin says:
        February 24, 2015 at 12:58 pm

        As a beginner something that simple may require more detail or understanding. I feel part 1 started with a lot of detail, and then it was just a do this or do that. Again I am just trying to help.

        Reply
  11. DmytryOn says:
    April 9, 2015 at 12:01 am

    None mentioned anything about UIAlertView being deprecated?

    Reply
    1. Jameson Quave says:
      April 16, 2015 at 12:58 pm

      It is deprecated, but this wasn’t updated to reflect that. I’ll work on that now.

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Connect

  • Facebook
  • Google+
  • My Programming Book Picks
  • Twitter

Jameson Quave


I write about new technologies and how we interact with them.
© 2025 Jameson Quave | Powered by Minimalist Blog WordPress Theme