7

cellForRowAtIndexPath:

cell.textLabel.text works fine.

UILabel is overlapping after scrolling. Here is the code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if (cell==nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

        // I have tried it by removing views and without.  No difference.   
        NSArray *viewsToRemove = [self.tableView subviews];
        for (UITableView *table in viewsToRemove)
        {
            [table removeFromSuperview];
        }
    }


    NSManagedObject *managedObject = [newClass objectAtIndex:indexPath.row];
    NSString  *entityName= [[managedObject entity]name];
    cell.textLabel.text = [NSString stringWithFormat:@"%@   %i", entityName, [indexPath row]];
    cell.textLabel.font=[UIFont systemFontOfSize:14.0];


    NSDate *date = [managedObject valueForKey:@"lastmoddate"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"EEE, MMM d, YYYY  h:mm a"];
    NSString *dateString = [formatter stringFromDate:date];

    UILabel *lblDate = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 215, 10)];
    lblDate.text = dateString;
    lblDate.textColor = [UIColor grayColor];
    lblDate.font = [UIFont systemFontOfSize:10.0];

    [lblDate setBackgroundColor:[UIColor clearColor]];
    [cell.contentView addSubview:lblDate];
    return cell;
}

Here is the image:

enter image description here

user1107173
  • 10,334
  • 16
  • 72
  • 117

10 Answers10

6

This is what I came up with and it works well:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell==nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    NSManagedObject *managedObject = [newClass objectAtIndex:indexPath.row];
    NSString  *entityName= [[managedObject entity]name];

    NSDate *date = [managedObject valueForKey:@"lastmoddate"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"EEE h:mm a MMM d, yy'''"];
    NSString *dateString = [formatter stringFromDate:date];

    UILabel *lblUser = [[UILabel alloc] initWithFrame:CGRectMake(30, 8, 215, 14)];
    lblUser.text = [NSString stringWithFormat:@"%@   %i", entityName, [indexPath row]];
    lblUser.textColor = [UIColor blackColor];
    lblUser.font = [UIFont systemFontOfSize:16.0];
    lblUser.tag = 1;
    [lblUser setBackgroundColor:[UIColor clearColor]];

    UILabel *lblDate = [[UILabel alloc] initWithFrame:CGRectMake(30, 21, 215, 20)];
    lblDate.text = dateString;
    lblDate.textColor = [UIColor grayColor];
    lblDate.font = [UIFont systemFontOfSize:12.0];
    lblDate.tag = 2;
    [lblDate setBackgroundColor:[UIColor clearColor]];

    if ((([cell.contentView viewWithTag:1]) && ([cell.contentView viewWithTag:2])))
    {
        [[cell.contentView viewWithTag:1]removeFromSuperview];
        [[cell.contentView viewWithTag:2]removeFromSuperview];
    }

    [cell.contentView addSubview:lblDate];
    [cell.contentView addSubview:lblUser];


    return cell;
}
user1107173
  • 10,334
  • 16
  • 72
  • 117
  • 1
    I spent top much time searching solution for problem just like yours. When init printed everything was ok but when start with scrolling labels were mixed, their positions were mixed. Basically your solution helped me a lot. Thank you – iWizard Feb 03 '15 at 23:27
2

dequeueReusableCellWithIdentifier:forIndexPath: is guaranteed to return a cell (either a new one, or one from the reuse queue), so your if (cell == nil) clause never gets executed -- that's why it doesn't make a difference whether you remove the views or not. The labels overlap because that's the way you're setting it up. The default label is on the left side of the cell, and lblDate is also on the left (10 points from the left). Even if you move lblDate to the right, it might not show, because I think the default label goes full width of the cell. It would be better to make a custom cell with two labels that you place where you want them.

You also need to test whether the label already exists before you add another one. You can give the labels a unique tag, and check for a view with that tag, or, the easier way, I think, is to just make a custom cell in the storyboard or xib, and add the labels there. Then you only need to add the content to them in code.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
2

Try this

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if (cell==nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    UILabel *lblDate = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 215, 10)];

    [cell.contentView addSubview:lblDate];
    }


    NSManagedObject *managedObject = [newClass objectAtIndex:indexPath.row];
    NSString  *entityName= [[managedObject entity]name];
    cell.textLabel.text = [NSString stringWithFormat:@"%@   %i", entityName, [indexPath row]];
    cell.textLabel.font=[UIFont systemFontOfSize:14.0];
lblDate.text = dateString;
    lblDate.textColor = [UIColor grayColor];
    lblDate.font = [UIFont systemFontOfSize:10.0];

    [lblDate setBackgroundColor:[UIColor clearColor]];

    NSDate *date = [managedObject valueForKey:@"lastmoddate"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"EEE, MMM d, YYYY  h:mm a"];
    NSString *dateString = [formatter stringFromDate:date];
    return cell;
}
iAppDeveloper
  • 1,088
  • 1
  • 8
  • 16
  • @KumarKl, no it will not. dequeueReusableCellWithIdentifier:forIndexPath: always returns a cell, so the if(cell == nil) clause will never execute, and lblDate will never be added. – rdelmar Aug 28 '13 at 05:23
  • Really? How are you creating your cells? In a storyboard? In a xib? – rdelmar Aug 28 '13 at 05:29
  • @rdelmar creating programatically – iAppDeveloper Aug 28 '13 at 05:31
  • Then do you register the class? I haven't seen a situation where dequeueReusableCellWithIdentifier:forIndexPath: didn't return a non-nil cell before. – rdelmar Aug 28 '13 at 05:32
  • @rdelmar : Yes I agree . But while we done with Programmatically . The 1st time Cell will get nil only ,Right ? that time its just get initialised from next time onwards for the same cell it will call to the **Else** part so that it won't get overlap by reframing of it . Its just changes the content of it. Situation is like **Scrolling Up and down of TableView** – Kumar KL Aug 28 '13 at 05:41
  • @KumarKl, No, it's not supposed to. According to Apple's docs, dequeueReusableCellWithIdentifier:forIndexPath: alway returns a valid cell -- if there's none in the reuse queue, it creates it from the storyboard, or from the xib or class that you registered. I'm not sure what you or iAppDeveloper are talking about when you say you create the cells programatically. In iAppDevelopers code, he says he's creating a UITableViewCell, not some custom class. – rdelmar Aug 28 '13 at 05:44
  • @rdelmar Then Why do we need to Check for the Cell is Nil ,If there should be a return Cell. **If(cell == Nil)**.. Silly question , Don't mind ... – Kumar KL Aug 28 '13 at 05:46
  • You don't. That's the point. But iAppDeveloper is saying this code works, and I'm trying to figure out why. I haven't seen a case where that clause would be executed when using dequeueReusableCellWithIdentifier:forIndexPath:. – rdelmar Aug 28 '13 at 05:47
  • @rdelmar Ok , If I Didn't create a cell over the StoryBoard or Xib . Then In the Programmatically also . As You said it should get generate a cell , Right>? – Kumar KL Aug 28 '13 at 05:50
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/36373/discussion-between-rdelmar-and-kumar-kl) – rdelmar Aug 28 '13 at 05:51
  • I Got this Exception : 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:' – Kumar KL Aug 28 '13 at 05:51
2

This is problem with recreating cell contents. Try with following code segment.

for(UIView *view in cell.contentView.subviews){  
        if ([view isKindOfClass:[UIView class]]) {  
            [view removeFromSuperview];   
        }
    }
Samitha K
  • 41
  • 2
2

Add this line:

[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

Before:

[cell.contentView addSubview:lblDate];
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Pavan kumar C
  • 393
  • 1
  • 4
  • 15
0

You are right in writing the code for removing all contents from cell's subview. But you wrote it at wrong place. UITableView's dequeueReusableCellWithIdentifier will return you the cell after it has been allocated and initialized once. So the code you wrote for removing the cell.contentView.subViews will never run and you get the Overlapped views.

You can either right that code in the else statement but I do not prefer that way. Why allocate and initialize all the contentView's every-time the UITableView needs cell. Rather I would create UILabel once and give it a tag to access it later. Like this:

 UILabel *lblDate = nil;
  if (cell == nil)
  {
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    lblDate = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 215, 10)];
    lblDate.textColor = [UIColor grayColor];
    lblDate.font = [UIFont systemFontOfSize:10.0];
    lblDate.tag = 1;
    [lblDate setBackgroundColor:[UIColor clearColor]];
    [cell.contentView addSubview:lblDate];
  }
  else
  {
    //get a reference to the label in the recycled view
    lblDate = (UILabel *)[cell.contentView viewWithTag:1];
  }
Puneet Sharma
  • 9,369
  • 1
  • 27
  • 33
  • UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; always returns a cell. I have to declare cell before the If statement. – user1107173 Aug 29 '13 at 18:17
  • Hey. We're looking for a part-time iOS developer to work with in India. Part-time would be 10-20hours a week. Let me know if yourself or someone you may know of is interested. We're a small team based out of San Francisco. – user1107173 Jan 11 '14 at 14:40
0

Try this code. Your problem will be resolved.

-(NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section     
{

    return [arrTableData count];

}


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

static NSString *CellIdentifier = @"Cell";

UILabel *lblName;

UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:CellIdentifier] autorelease];

    lblName = [[[UILabel alloc] initWithFrame:CGRectMake(10, 20, 300, 20.0)] autorelease];
    lblName.tag = LBLNAME;
    lblName.numberOfLines=1;
    lblName.textAlignment=UITextAlignmentLeft;
    lblName.font = [UIFont systemFontOfSize:16.0];
    lblName.textColor = [UIColor blackColor];
    lblName.backgroundColor = [UIColor clearColor];
    lblName.autoresizingMask = UIViewAutoresizingFlexibleRightMargin  ;
    [cell.contentView addSubview:lblName];

}else{

    lblName = (UILabel *)[cell.contentView viewWithTag:LBLNAME];
}
if (arrTableData.count>0) { lblName.text=[NSString stringWithFormat:@"%@",[arrTableData objectAtIndex:indexPath.row]];

}

return cell;}
user1107173
  • 10,334
  • 16
  • 72
  • 117
Mahesh
  • 526
  • 1
  • 6
  • 21
  • Where is arrTableData coming from? – user1107173 Aug 29 '13 at 18:18
  • Its the TableView Data Source array which contains the data to be displayed in tableview. You can initialize it with some objects as per your requirement and reload the table. – Mahesh Aug 30 '13 at 05:04
0

Try This

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


static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];

NSManagedObject *managedObject = [newClass objectAtIndex:indexPath.row];
NSString  *entityName= [[managedObject entity]name];

NSDate *date = [managedObject valueForKey:@"lastmoddate"];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"EEE h:mm a MMM d, yy'''"];
NSString *dateString = [formatter stringFromDate:date];

UILabel *lblUser = [[UILabel alloc] initWithFrame:CGRectMake(30, 8, 215, 14)];
lblUser.text = [NSString stringWithFormat:@"%@   %i", entityName, [indexPath row]];
lblUser.textColor = [UIColor blackColor];
lblUser.font = [UIFont systemFontOfSize:16.0];
lblUser.tag = 1;
[lblUser setBackgroundColor:[UIColor clearColor]];

UILabel *lblDate = [[UILabel alloc] initWithFrame:CGRectMake(30, 21, 215, 20)];
lblDate.text = dateString;
lblDate.textColor = [UIColor grayColor];
lblDate.font = [UIFont systemFontOfSize:12.0];
lblDate.tag = 2;
[lblDate setBackgroundColor:[UIColor clearColor]];



[cell.contentView addSubview:lblDate];
[cell.contentView addSubview:lblUser];


return cell;
}
0
if ([cell.contentView viewWithTag:tagnumber]
    {
        [[cell.contentView viewWithTag:tagnumber]removeFromSuperview];

    }
lblDate.tag = tagnumber;
    [cell.contentView addSubview:lblDate];

this line is enough just remove the previous tag subviews and added new subview with tag .. Thanks for your answer

abdul sathar
  • 2,395
  • 2
  • 28
  • 38
0

In my case same issue is happened,allocating the tableviewcell in 2places,one is allocated in tableviewcell custom class,and customview controller has to been allocated,after i was changed the alllocation then everything will be working fine.

Preetha
  • 753
  • 9
  • 12