overkill overkill - 1 month ago 8
iOS Question

Set hidden data to uitableview cell

I sarched a bit here and on google, but I couldn't really find unearthing that I could clearly understand. Basically what I'd like to do is display a list of names, then when clicking on the table add the ID of those names to another array, along with their ID. The solution I'm working on at the moment is based on nested NSMutableArrays but I don't know if that's the best thing to do. I think it would be ideal to have another "field" to write on in the cell (by field I mean something like cell.text) so that I could store my hidden value.

Is there a way to do so?!

Answer

You need to adjust your thinking. Cocoa strongly follows the MVC (Model View Controller) design pattern, and you should learn to think that way.

In MVC, the model is the part of the program that stores your data. The View is what displays information to the user and interacts with the user.

The controller is the brains that serves as the control logic and feeds data back and forth between the model and the view.

In UIKit, objects with View in their name are view objects, and objects with controller in their name are controller objects. As a general rule the model object is up to you, as its application specific.

A table view is a view object. It doesn't store information, it presents it to the user and/or collects it from the user.

An array usually is the best choice for storing the data that gets presented in a table view. If you have a table view with multiple sections and multiple rows in each section than an array for each section, containing an array with data for each row is a good choice. Unless you have a sectioned table view forget about that however. It'll just confuse you.

For a "flat" table view with only one section, a single array is usually what you want.

How you store the data that you display in a cell is a design question. One easy answer is to use a dictionary for the data in each cell. So you wind up with an array of dictionaries.

If you're comfortable creating custom objects the a custom data storage object makes your code a little cleaner. However, you will probably want to implement the NSCoding protocol in your data objects so you can save them to disk easily.

Using an array to store the data for a cell is NOT a very good choice, because arrays use numeric indexes for their data. You might have a name that you want to display in your cell, and an image, and an employee ID, and a salary, and a few other things. What numeric indexes should you use for those values? Not clear. Now, if you use a dictionary, you can use meaningful keys:

cellData[@"name"]
cellData[@"imageName"]

or better yet, define constants for your keys:

#define kNameKey @"name"
#define kImageNameKey @"imageName"

then

cellData[kNameKey]
cellData[kImageNameKey]

That way you don't risk mis-typing the key string somewhere and introducing a bug that you have to go figure out.

If you're a beginner you might want to start out with an array of dictionaries. After you've used that approach for a while you might decide to migrate to custom data objects.

Let's assume we're using a dictionary to store the data for each cell from now on.

Now, to your question. It's perfectly ok to store more information in the dictionary for each cell than you display at any one time. The data isn't really hidden, it's just not (yet) displayed. Then, if the user takes an action that means you want to expose additional data, tell the table view to reload that cell. You might want to keep an array of info about the status of each cell (e.g. a bool that tells if the table view should display the salary info for each entry in your data array.) When the user does something that changes the info you want to display, change the appropriate setting in that index in the display status array and tell the table view to reload that cell. In your cellForRowAtIndexPath method, you would check the display status array for what to display for that cell, then fetch the appropriate data and install it into the cell (and clear out fields that should not be shown, since they might be left over from the last time the cell was used.)

If you have an array of dictionaries, then your cellForRowAtIndexPath method might look up the attributes of an entry like this:

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  NSInteger row = indexPath.row;
  NSDictionary *rowData = dataArray[row]
  NSString *name = rowData[kNameKey];
  NSString *imageName = rowData[kImageNameKey];
}