Victor C.
Victor C.

Reputation: 191

Custom UITableViewCell with dynamic content

I'm trying to create a UITableView which loads a custom cell from a XIB. I have EventsCell.xib along with the .m and .h files.

The cell's content and height are dynamic, as it can contain an unknown number of subviews.

This is the code that loads the cells.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"EventsCellIdentifier";

        EventsCell *cell = (EventsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) 
        {
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"EventsCell" owner:self options:nil];
            cell = [nib objectAtIndex:0];        
        }

        NSDictionary *hour = [[[eventsArray objectAtIndex:[indexPath section]] valueForKey:@"hours"] objectAtIndex:[indexPath row]];

        NSArray *events = [hour valueForKey:@"events"];

        cell.events = events;
        cell.timeLabel.text = [hour valueForKey:@"name"];

        int offset = 0;
        for(NSDictionary *event in events)
        {
            UIView *vvv = [[UIView alloc] initWithFrame:CGRectMake(50, offset, 270, 44)];
            [vvv setBackgroundColor:[UIColor clearColor]];

            UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)];
            lab.text = [event valueForKey:@"name"];
            lab.backgroundColor = [UIColor clearColor];

            [vvv addSubview:lab];

            [cell.contentView addSubview:vvv];

            offset += 44;
        }    

        return cell;
    }

It loads the cells, but after i scroll a few times on the table view, the content looks like this:

enter image description here

What am i doing wrong?..

Thank you!

==================== UPDATE ====================

Now another thing is happening. I've added all of the elements of the subviews i add to the cell in a separate view controller. Like bellow.

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"EventsCellIdentifier";

        EventsCell *cell = (EventsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) 
        {
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"EventsCell" owner:self options:nil];
            cell = [nib objectAtIndex:0];        
        }

        for (UIView *subV in [cell.contentView subviews]){
            [subV removeFromSuperview];
        }    

        NSDictionary *hour = [[[eventsArray objectAtIndex:[indexPath section]] valueForKey:@"hours"] objectAtIndex:[indexPath row]];

        NSArray *events = [hour valueForKey:@"events"];

        cell.events = events;
        cell.timeLabel.text = [hour valueForKey:@"name"];

        int offset = 0;

        for(NSDictionary *event in events)
        {
            EventBoxViewController *ebvc = [[EventBoxViewController alloc] initWithNibName:@"EventBoxViewController" bundle:nil];
            ebvc.nameLabel.text = [event valueForKey:@"name"];

            [ebvc.view setFrame:CGRectMake(50, offset, 270, 44)];
            [cell.contentView addSubview:ebvc.view];

            offset += 44;
        }    

  return cell; 
 }

And they don't load as they should. Please see the image below.

enter image description here

They load only when i scroll through the cells and even then they don't load as they should. Also the text for the label does not get assigned. Any ideas on what i am doing wrong?

Thank you.

Upvotes: 1

Views: 2633

Answers (3)

Vanya
Vanya

Reputation: 5005

More readable solution is instead of dequeueing a cell, to create one every time, but it depends how many of them you need to load in the end because of overhead. This removing thing looks nasty.

Upvotes: 0

Undye
Undye

Reputation: 11

It works if you add a UIVIew* to your table cell prototype and clear it's sub-views. like this:

 UIView* editView = (UIView*)[cell viewWithTag:102];
 for (UIView *subV in [editView subviews]){
        [subV removeFromSuperview];

Upvotes: 1

D25
D25

Reputation: 283

Views are added on cell.contentView, Since the cells are reuable it still remains added, If we remove all the subViews it will work

for (UIView *subV in [cell.contentView subviews]){
     [subV removeFromSuperview];
}

Add the above code after

if (cell == nil) 
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"EventsCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];        
}

Upvotes: 4

Related Questions