10

I need a grouped UITableView similar to the one for Twitter accounts in Settings app:

Twitter accounts

That is, a sort of form or menu where some of the sections have a beforehand known set of static cells, and some other sections have to be dynamic and allow inserting additional rows the same way the "Add Account" does here. I'm managing the UITableView in a .xib file. For the static cells, I have separated .xib files that I can load within the cellForRowAtIndexPath: method in the view controller.

How should I handle this kind of table? I don´t find any example code.

How the cellForRowAtIndexPath: method should look like? May I need to keep strong properties for the static cells? Would it be better to design each static cell directly within the same .xib file where the table view is, and to set outlets for them? (Though this does not allow to reuse my custom cells design...)

I need some guidelines for achieving this and correctly managing cells and memory. Thanks in advance

AppsDev
  • 12,319
  • 23
  • 93
  • 186
  • I don't think you can mix static cells with dynamic ones -- it's a property of the table view itself, so I think it needs to be one or the other. There's nothing you can't do with a dynamic cell that you can do with a static one, so just make it all dynamic. – rdelmar Jul 12 '13 at 04:28
  • @rdelmar Ok, maybe I'm naming things in the wrong way... what I want to mean with "static" and "dynamic" is just that I have a set of sections whose cells I already know and won't change (as the Twitter logo cell and the "Update contacts" cell in the screenshot), and another set of sections that will have a variable set of cells as users provide new information (as "Add Account") – AppsDev Jul 12 '13 at 05:50
  • @rdelmar Since there are existing examples of what I need (the screenshot I provided, and the "New contact" functionality in the Phone app, for example), it'd be possible to do... the question is, how? I'm not using storyboards... – AppsDev Jul 12 '13 at 05:53
  • But you don't know that they used a mixture of static and dynamic cells to achieve that look. The example I posted gives that same look with only dynamic cells. – rdelmar Jul 12 '13 at 05:59
  • @rdelmar You're right, we don`t know the implementation details of such table... I just want to get the same appearance and functionality, as you described – AppsDev Jul 12 '13 at 06:17

2 Answers2

29

Dynamic prototype cells can behave like static ones if you just return the cell without adding any content in cellForRowAtIndexPath, so you can have both "static like" cells and dynamic ones (where the number of rows and the content are variable) by using dynamic prototypes.

In the example below, I started with a table view controller in IB (with a grouped table view), and changed the number of dynamic prototype cells to 3. I adjusted the size of the first cell to 80, and added a UIImageView and two labels. The middle cell is a Basic style cell, and the last one is another custom cell with a single centered label. I gave them each their own identifier. This is what it looks like in IB:

enter image description here

Then in code, I did this:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.theData = @[@"One",@"Two",@"Three",@"Four",@"Five"];
    [self.tableView reloadData];
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 1)
        return self.theData.count;
    return 1;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0)
        return 80;
    return 44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell;

    if (indexPath.section == 0) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"TitleCell" forIndexPath:indexPath];

    }else if (indexPath.section == 1) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"DataCell" forIndexPath:indexPath];
        cell.textLabel.text = self.theData[indexPath.row];

    }else if (indexPath.section == 2) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"ButtonCell" forIndexPath:indexPath];
    }

    return cell;
}

As you can see, for the "static like" cells, I just return the cell with the correct identifier, and I get exactly what I set up in IB. The result at runtime will look like your posted image with three sections.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Thanks for the explanation and the code snippet. If instead of having the cells as outlets in the IB, I load them from their own `xib` file (in order to being able to reuse a cell custom style in other tables), how should the `cellForRowAtIndexPath:` method look like? I need to link the cells to strong properties? – AppsDev Jul 12 '13 at 06:14
  • 1
    @AppsDev, it wouldn't look any different. You would just have to register the nibs in viewDidLoad. So for each type of cell you need to write something like: [self.tableView registerNib:[UINib nibWithNibName:@"YourNibNameHere" bundle:nil] forCellReuseIdentifier:@"TitleCell"]; You don't need any properties. – rdelmar Jul 12 '13 at 06:20
  • thanks! Then if I want to access the controls within my custom cells (I have text fields and switches), would it be better to look for the cells in the table as needed, rather than keeping references for each individual cell? – AppsDev Jul 12 '13 at 06:25
  • sorry for my lack of knowledge... do I need to register the nib once for each cell I want, even if I have several cells "coming" from a same nib? – AppsDev Jul 12 '13 at 06:42
  • @AppsDev, yes, once for each cell type since each needs a different identifier. – rdelmar Jul 12 '13 at 14:31
  • Great answer. I found that in addition to this, if you want multiple static cells but with different content within the same section, you can name their `identifier`s in the storyboard to something like `Section1Row3`, then in your `cellForRowAtIndexPath`, use something like this for those sections: `[tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"Section%iRow%i", (int)indexPath.section, (int)indexPath.row]]` – rebello95 Mar 05 '15 at 18:01
2

Static is just a provision on top of dynamic layout. Basically static is a WYSIWYG.

If you are not resistant to experiment with values, I would recommend go dynamic. There are hundreds of examples available, such as this and this.

As you go further, you would see yourself diverging towards two options when customizing dynamic table views:

  • Subclass UITableViewCell (more effort , but good in the long run). Again, follow this.
  • Play with UITableViewCell properties inside cellForRowAtIndexPath: (less effort and quick result but may or may not be performance-friendly due to possible redrawing)

The possibilities are endless, such as here where cell background view is customized.

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89