Gold: tableView(_:heightForRowAt) crash when using tableView.numberOfRows(inSection)


#1

In the gold challenge, I am using the tableView(_:heightForRowAt) method to set the row height. I had no issues when I used the following:

if indexPath.section == 1 && indexPath.row == cheapItems.count {
        return 44
    }
    else {
        return 60
    }

where cheapItems is my array of items whose valueInDollars is at most $50 and the item with the text "No more items!" is the last element in cheapItems.

But I wanted to see if there is a way to use properties/methods to retrieve the number of sections and rows in the if statement. I then used tableView’s property numberOfSections and tried to use tableView’s method numberOfRows(inSection). Using this method (not the property), the app crashes and I get all sorts of messages in the debugging navigator.

I have added print statements in all of the methods in ItemViewController to get a sense of the order of these methods being called. First of all, I have found the order and multiplicity of the methods calls to be surprising and I do not understand the algorithms behind all of that (even before the app crashing on this method). But here are my questions:

  1. My suspicion for the crash is that the method tableView(_:heightForRowAt) is called too early for the number of rows in each section to be determined, which is what tableView.numberOfRows(inSection) returns. My console log is below to help one see this. Does anybody have a better explanation for the app crashing.

  2. My second question is about the debugging navigator. I have no errors in the Issue Navigator; neither in the buildtime or the runtime. I am not sure what other “time” there is. But apparently my debugging navigator shows quite a mess. So why do I have no buildtime or runtime errors, but a bunch or issues in the debugging navigation?

  3. The debugging navigation shows a bunch of threads with hundreds of items in them. There is an arrow pointing to the 7th one of the first thread, and in the text editor that arrow points to a highlighted line where I call a print statement (for the tableView(_:titleForHeaderInSection) is called). This print statement did not cause an issue until the tableView.numberOfRows(inSection) was called. In the debugging navigation, that 7th line says ItemsViewController.tableView(UITableView, titleForHeaderInSection: Int) -> String? .

My question is, I don’t know how to understand what all this is telling me. There are hundreds of items like this. In this case, I think I know the issue. But to become a professional, how to better understand what these messages are telling me?

Here is the console print statements (I am showing this when the app does not crash by simply returning 60 in the method):

AppDelegate is called and the item names/values are:
item name: Shiny Spork, item value: 20
item name: Rusty Bear, item value: 4
item name: Rusty Bear, item value: 71
item name: Rusty Bear, item value: 89
item name: Rusty Bear, item value: 90
viewDidLoad() is called
numberOfSections method is called
numberOfSections method is called
tableView(:titleForHeaderInSection) is called for section 1
tableView(
:numberOfRowsInSection) is called for section 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:titleForHeaderInSection) is called for section 0
tableView(:numberOfRowsInSection) is called for section 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
numberOfSections method is called
tableView(:titleForHeaderInSection) is called for section 1
tableView(
:numberOfRowsInSection) is called for section 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:titleForHeaderInSection) is called for section 0
tableView(:numberOfRowsInSection) is called for section 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
numberOfSections method is called
tableView(:titleForHeaderInSection) is called for section 1
tableView(
:numberOfRowsInSection) is called for section 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:titleForHeaderInSection) is called for section 0
tableView(:numberOfRowsInSection) is called for section 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
numberOfSections method is called
tableView(:titleForHeaderInSection) is called for section 1
tableView(
:numberOfRowsInSection) is called for section 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:titleForHeaderInSection) is called for section 0
tableView(:numberOfRowsInSection) is called for section 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
numberOfSections method is called
tableView(:titleForHeaderInSection) is called for section 1
tableView(
:numberOfRowsInSection) is called for section 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:titleForHeaderInSection) is called for section 0
tableView(:numberOfRowsInSection) is called for section 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:cellForRowAt) is called for section 0 and row 0
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:cellForRowAt) is called for section 0 and row 1
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:cellForRowAt) is called for section 0 and row 2
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:cellForRowAt) is called for section 1 and row 0
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:cellForRowAt) is called for section 1 and row 1
tableView(
:heightForRowAt) called
tableView(:heightForRowAt) called
tableView(
:cellForRowAt) is called for section 1 and row 2
tableView(:heightForRowAt) called
tableView(
:heightForRowAt) called
tableView(:titleForHeaderInSection) is called for section 0
tableView(
:titleForHeaderInSection) is called for section 1


#2

I don’t have the full picture, but the second clause of the test expression looks a bit buggy.

Row numbers are zero-based: in a section, the index of the first row is 0, and that of the last row is one less than the number of rows in the section.


#3

I can see why you say that. But I don’t think that is an issue here. Thats because in that approach, I was adding an extra cell that says “No more items” at the end of the section 1. So the cheapItems.count th row of section 1 is this the exceptional cell that gets the smaller font.


#4

There is a method in UITableViewDelegate (heightForRowAt indexPath:) given as

 override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        var myHeight: CGFloat = 0.0
        if indexPath.section == 2 {
            myHeight = 44.0
        } else {
            myHeight = 60.0
        }
        return myHeight
    }

#5

I got the exact same error. Would love to hear any fresh ideas out there - this was very confusing.