views:

205

answers:

3

I'm trying to add an additional cell for custom content as the last cell in a tableView, without altering the dictionary that creates the other content of the table. I think the place to add it is in cellForRowAtIndexPath rather than adding one to the numberOfRowsInSection, which just crashes if I do.

I get a cellCount from the dictionary that creates the data for the table, then in cellForRowAtIndexPath, I have:

if (indexPath.row == cellCount) {
        ... stuff goes here
            return cell;
                        } 

of course, this never gets called. If I do if (indexPath.row == cellCount -1) it overwrites the last cell with content.

I can get this to work if I add a blank entry into the xml from which I am populating the dictionary, but that's ugly.

Example code would be neat!

+1  A: 

First you need to modify the numberOfRowsInSection to return +1. Then in cellForRowAtIndexPath you need to add that extra blank cell.

willcodejavaforfood
Unfortunately, when I try to return a value greater than the count of the node within the dictionary it crashes with a 'beyond bounds' error. This is because several tables are being created from those nodes. Table1 show some data (10 cells), table2 shows other data (8 cells, variable) and table3 more data (10 or more cells). The number of cells in each table is determined by the keys in the dictionary which are different in number.
Michael
+1  A: 

The problem here is that tableviews are designed to easily and accurately display the contents of you data-model and you've decided you don't want to do that. You're fighting the API.

The straight forward way to do this would be to put a check in numberOfRowsInSection such that it adds one to the row count when you want to display the input row. Then in cellForRowAtIndexPath: you will need to check if the table view is asking for the input row and return the appropriate type of cell.

From a UI design point, you might want to consider whether this setup is the best. This isn't a standard setup. Is the user going to understand that they can only edit the last row of the table? Will they understand they can't edit the other rows? Does anything in the UI tell them how all this works? Does the user have to scroll to the end of the table every time they want to add data? How long can this table grow? How will displaying a keyboard for the last row of the table affect how table scrolls?

I think it would be a better design to use a footer view to display the text field such that is is visually distinct from the rest of the table. It would be programmatically simpler as well. You wouldn't have to check if the table was asking for the last row every single time it ask for a cell.

Edit:

In thinking about it, perhaps a sectioned table would be simpler. Just put the special row in its own section (with or without a header.) That would simplify you handling of the rows that source from the dictionary because the row count in that section would always be the count of the dictionary. Likewise, you could just check the section attribute of the indexpath to know what cell to return for what row.

TechZen
Thanks TechZen. The cell in question is not for editing. It will present a summary of the data presented above, so it will be something I add to the cell, just not from the dictionary.
Michael
See my edit above for another idea.
TechZen
Excellent suggestion, and, I'm sure this would work if I were not drawing 3 tables from the data. The app tables go something like this: Country -> States -> Major Cities I need the 2nd section only on Major Cities table and I cannot go back and add a section once the table is drawn. If I create two sections, the first two tables would duplicate the data of the first section.
Michael
It should possible to display as you want with the same data you just need separate delegates and datasources for each table. Of course, I can't see your data model so I can't really advise further.
TechZen
+1  A: 

You need to provide for the extra cell in both cellForRowAtIndexPath and numberOfRowsInSection.

Assuming that cellCount is the actual number of cells in your array then: (a) in cellForRowAtIndexPath return the extra custom cell when indexPath.row == cellCount, and (b) in numberOfRowsInSection you need to return cellCount+1.

Assuming a single section, an example would go something like this:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{ 
    return [journalArray count] + 1;    // add 1 for summary
} 

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    if (indexPath.row < [journalArray count]) {
        return [journalArray objectAtIndex:indexPath.row];
    } else {
        return summaryCell;
    }
}
progrmr