Question about the gold challenge


#1

Ok so I completed the gold challenge. Everything works great. I just have a few questions…

First, I used tableView:heightForRowAtIndexPath: which worked great. But the docs say this method could lead to performance issues with 1000’s of table rows, which makes sense because it’s called for every row. I tried to set the rowHeight property explicity in tableView:cellForRowAtIndexPath:, which I thought was ok to do judging by what the docs say. The docs state:

Trying to set the rowHeight explicity didn’t do anything for me (this was before I implemented tableView:heightForRowAtIndexPath:). Did I try to set it in the wrong method?? I figured it had to be in tableView:cellForRowAtIndexPath: because I needed to set the height to 60.0 if it wasn’t the “No more items” row.

Second question, I looked at a few other’s examples after I finished mine, to gauge how I did. There are some people that explicitly put , is this necessary? My code doesn’t throw any errors or warnings. If the chapter is followed word for word the ItemsViewController’s superclass is UITableViewController, which if I remember correctly, acts as the UITableView Datasource and Delegate. If we inherit from UITableViewController, we shouldn’t need to put correct?


#2
  1. Where did you put setRowHeight:? Make sure it is in viewDidLoad and not in the init method.

  2. UITableViewController does conform to UITableViewDelegate, so subclasses need not explicitly conform to it.


#3

How can I differentiate between different cell types (i.e. the “last cell” and the rest of the cells) in viewDidLoad?


#4

There is no difference between the cells, the only difference is the model data. You can determine whether you should use the model data (the items array) or not by checking the row the cell is for. For example, if you have 10 items but 11 cells, the 11th cell should be the one that displays the static string instead of pulling from the items array.


#5

This answer is somewhat confusing to me (sorry slowly learning here).

I understand what you’re saying about using rows to determine what needs custom heights, but I am with Brandon in not understanding how you should do that in viewDidLoad.

Currently, I implement the delegate (which Apple seems to advise against) and I set all of my contents within the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method like so:

[code] //create local var for the label
NSString *label = @"";

//check for a reusable cell first, use that if it exists
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];

// if there is no reusable cell of this type, create a new one
if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
}

NSArray *currentSection = [tableData objectAtIndex:[indexPath section]];

if ([indexPath row] < [currentSection count]) {
    BNRItem *p = [currentSection objectAtIndex:[indexPath row]];
    label = [p description];
}

else{
label = @“No More Items”;
}

[[cell textLabel] setText:label];
return cell;[/code]

In terms of setting row heights, it seems that Apple has only provided the delegate method or the setRowHeight method which is only applicable to a UITableView objects, not it’s specific contained cell rows.

I’ve searched all the other solutions in the forum and online and it seems they all use the delegate method and put the row height definitions outside of viewDidLoad.


#6

If you have a constant row height (i.e., the same height for each row), you’ll send setRowHeight: to the table view.

If you have variable row height, you’ll implement the delegate method to return a value depending on the index path.

Thus, in viewDidLoad, you’ll do [tableView setRowHeight:80] for a constant row height. Doing it in viewDidLoad guarantees that a low memory warning won’t change your row height (as opposed to doing it in init, which means that only the first time your ItemsVIewController loads its view will it have this new row height.) You won’t be able to change the rowHeight once you are already in cellForRowAtIndexPath:.

For the variable height, you won’t call setRowHeight: (ever), but instead will implement the method like so:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *currentSection = [tableData objectAtIndex:[indexPath section]];
    
    if ([indexPath row] < [currentSection count]) {
        return 44.0;
    }
   else{
      return 60.0;
   }
   return 44.0;
}

#7

Yeah that makes sense, thanks Joe. I think the reason we were worried was just because the documentation seemed to worn against using the delegate method as it would have a notable impact on the application’s efficiency if it exceeded 1000 rows. That doesn’t apply in our case so I put it together as you had suggested. Was just wondering how you would do variable row heights in a setting that exceeded the 1000 row max that the docs mention.

Thanks for your help!