3

Here's what I am trying to do ultimately. I want to display a menu of items in a UITableView, but dynamically, so that the type of item displayed determines the custom cell view loaded. For example, let's say the menu item type is 'switch', then it will load a nib named 'switch.xib' and the state will be on/off depending on that particular menu item's value. There may be 5 items that are "switch" type, but different values. So I want to use the same xib for each one, but 5 instances.

So, long way around to the question. When I load the cell view from the nib, I would think it would need unique reuse identifiers for the dequeue for when it scrolls back on the screen, right? (Unique for each instance, i.e. each menu item.) In the UITableViewCell in Interface Builder, I see where I can set a reuse identifier property, but I want to set it at run time for each instance of the switch. For example, Menu Item #1 is a switch, #2 is a text field, #3 is a switch, etc. So #1 and #3 both need unique cell ID's to dequeue.

Here's what my cellForRowAtIndexPath looks like:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Cells are unique; dequeue individual cells not generic cell formats
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];

ITMenuItem *menuItem = [menu.menuItems objectAtIndex:indexPath.row];

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    // Load cell view from nib
    NSString *cellNib = [NSString stringWithFormat:@"MenuCell_%@", menuItem.type];
    [[NSBundle mainBundle] loadNibNamed:cellNib owner:self options:nil];
    cell = myCell;
    self.myCell = nil;
}
// Display menu item contents in cell
UILabel *cellLabel = (UILabel *) [cell viewWithTag:1];
[cellLabel setText:menuItem.name];
if ([menuItem.type isEqualToString:@"switch"]) {
    UISwitch *cellSwitch = (UISwitch *) [cell viewWithTag:2];
    [cellSwitch setOn:[menuItem.value isEqualToString:@"YES"]];
}
else if ([menuItem.type isEqualToString:@"text"]) {
    UITextField *textField = (UITextField *) [cell viewWithTag:2];
    [textField setText:menuItem.value];
}

return cell;
}
Zouhair Sassi
  • 1,403
  • 1
  • 13
  • 30
Jay Imerman
  • 4,475
  • 6
  • 40
  • 55
  • What is your question? What problem are you having? What error messages? – Robotic Cat Nov 14 '12 at 01:05
  • Sorry, perhaps it is a little difficult to word clearly. The question is, how can I tag the cell with a reuse identifier when I allocate it, so that the dequeue will work? – Jay Imerman Nov 14 '12 at 01:09

4 Answers4

0

You can set the reuse identifier in the nib file. So for switch.xib you would use 'switch' as the reuse identifier. Then just change

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];

to

NSString *CellIdentifier = menuItem.type;

assuming that menuItem.type is 'switch'

Alejandro
  • 3,726
  • 1
  • 23
  • 29
  • Correct, menuItem.type is 'switch', 'text', etc. The problem with this is there will be no uniqueness for the individual instances of it; say I have 5 'switch' menu items in the same menu, won't that be an issue? Maybe it won't be, perhaps I am over thinking it. – Jay Imerman Nov 14 '12 at 01:29
  • Yeah, that's exactly what you want. Having the same reuse identifier will mean that one instance of the 'switch' cell can be reused for a different switch. – Alejandro Dec 07 '12 at 17:31
  • In my case, small number of menu items, it seemed to work fine without growing memory usage to not dequeue the cells at all. I don't know if it will cause an issue if it tries to display multiple "switch" cells, for example, on screen at once. Probably not, as the only dequeues will be cells scrolled off the screen. Since the menus are not long, there won't be much queuing anyhow. Thanks for the tip! – Jay Imerman May 03 '13 at 18:33
0
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if(cell == nil)
    {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    TextFieldFormElement *item = [self.formItems objectAtIndex:indexPath.row];
    cell.labelField.text = item.label;
    return cell;
}
Daniel
  • 10,864
  • 22
  • 84
  • 115
Bhushan_pawar
  • 157
  • 1
  • 5
0

Your custom cell from xib file can be loaded in a way like this. The xib file name is the same as the cell class name and the reuse id.

- (YourCell *)tableView:(UITableView *)_tableView getCellWithId:(NSString *)cellId
{
        YourCell *cell;

        /* Cell id and xib have the same name. */
        cell = [_tableView dequeueReusableCellWithIdentifier:cellId];
        if (cell == nil) {
                NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellId owner:self options:nil];
                cell = [nib objectAtIndex:0];
        }
        return cell;
}
Cynichniy Bandera
  • 5,991
  • 2
  • 29
  • 33
-1

For my idea, if your types are not too much design each cell in different xib and swift file. Mainly for performance issues.

If not possible to dequeue, give them different identifier. You can register more than one identifier for tableview or collection view (one of our apps using 12 different cells this way.)

But handling IBActions will be little messy this way.

Canberk Ersoy
  • 428
  • 1
  • 5
  • 13