Adding unknown number of rows to 'Static Cells' UITableView Adding unknown number of rows to 'Static Cells' UITableView xcode xcode

Adding unknown number of rows to 'Static Cells' UITableView


To add dynamic cells to a static cells table you have to override every UITableView delegate method that has an indexPath.

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath-(NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

.

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{     return NO;}-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{          return NO;}-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{          return UITableViewCellEditingStyleNone;     }- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{     int section = indexPath.section;     // if dynamic section make all rows the same height as row 0     if (section == self.dynamicSection) {          return [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];     } else {          return [super tableView:tableView heightForRowAtIndexPath:indexPath];     }}- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{     int section = indexPath.section;     // if dynamic section make all rows the same indentation level as row 0     if (section == self.dynamicSection) {          return [super tableView:tableView indentationLevelForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];     } else {          return [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath];     }}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{     if (section == self.dynamicSection ) {          return [self.dataListArray count];     } else {          return [super tableView:tableView numberOfRowsInSection:section];     }}-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{     int section = indexPath.section;     int row = indexPath.row;     if (section == self.dynamicSection) {          // make dynamic row's cell          static NSString *CellIdentifier = @"Dynamic Cell";          UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];          if (!cell) {               cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];          }          cell.textLabel.text = [self.dataListArray objectAtIndex:row];          return cell;    } else {          return [super tableView:tableView cellForRowAtIndexPath:indexPath];    }}

Only once you have every method overridden will your table start to work. For any referencing the static section, just refer to [super].


Darren's answer gave me the idea for what worked for me, however I didn't have to go so far as to implement every single tableView delegate method. You really only need to override numberOfRowsInSection and cellForRowAtIndexPath.

First I defined a static table in Interface Builder with 4 sections, 2 to 4 cells per section. I wanted section 0, 2 and 3 to be static and look exactly as they did in IB, but I wanted section 1 to have a custom number of rows with a custom display in each cell based on an array of values I had.

In the view controller for the static table, override the number of cells returned for your dynamic section, but accept the defaults for all other sections (they'll fall back to the IB values). Do the same for cellForRowAtIndexPath and return the [super] implementation for all sections except section 1.

@implementation myMostlyStaticTableViewController@synthesize myFancyArray;- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger) section{    if (section == 1)        return [myFancyArray count]; // the number of rows in section 1    else        return [super tableView:tableView numberOfRowsInSection:section];}- (UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{    // for cells not in section 1, rely on the IB definition of the cell    if (indexPath.section != 1)        return [super tableView:tableView cellForRowAtIndexPath:indexPath];    // configure a task status cell for section 1    MyCustomTableViewCell *cell;    cell = [tableView dequeueReusableCellWithIdentifier:@"myCustomCell"];    if (!cell)    {        // create a cell        cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"myCustomCell"];    }    cell.myCustomLabel.text = [myFancyArray objectAtIndex:indexPath.row];    return cell;}@end

And of course you need a custom cell:

@implementation MyCustomTableViewCell- (UITableViewCell *) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{    // initialize cell and add observers    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];    if (!self)        return self;    self.clipsToBounds = YES;    self.selectionStyle = UITableViewCellSelectionStyleNone;    // configure up some interesting display properties inside the cell    _label = [[UILabel alloc] initWithFrame:CGRectMake(20, 9, 147, 26)];    _label.font = [UIFont fontWithName:@"HelveticaNeue-Medium" size:17];    _label.textColor = [UIColor colorWithWhite:0.2 alpha:1];    [self.contentView addSubview:_label];    return self;}@end


I will post answer in Swift, but it should work in Objective-C as well.

In my experience, it was enough to override these methods in UITableViewController:

tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> InttableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCelltableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloattableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int

If you want to have custom table view cell in your table view, you need to crate subclass of UITableViewCell also with nib, and register it to your table view.

My whole controller looks like this:

var data = ["Ahoj", "Hola", "Hello"]override func viewDidLoad() {    super.viewDidLoad()    tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "reuseIdentifier")}// MARK: - Table view data sourceoverride func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {    if section == 1 {        return data.count    }    return super.tableView(tableView, numberOfRowsInSection: section)}override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {    if indexPath.section == 1 {        let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! CustomCell        cell.titleLabel.text = data[indexPath.row]        return cell    }    return super.tableView(tableView, cellForRowAtIndexPath: indexPath)}override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {    return 44}override func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int {    return 0}override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {    tableView.deselectRowAtIndexPath(indexPath, animated: true)    if indexPath.section == 1 {        print(data[indexPath.row])    }}@IBAction func addItem() {    data.append("Item \(data.count)")    tableView.beginUpdates()    tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: data.count - 1, inSection: 1)], withRowAnimation: .Left)    tableView.endUpdates()}@IBAction func removeItem() {    if data.count > 0 {        data.removeLast()        tableView.beginUpdates()        tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: data.count, inSection: 1)], withRowAnimation: .Left)        tableView.endUpdates()    }}