0

I have a TableView with CoreData and Custom Cells which all works fine.

now when I select a cell to have its content edited and return from it, by just tapping the back button in a UINavigationController, I have something strange happen.

Please see the images what I mean. It seems that the updated UILabels are being placed on top of the old ones instead of being 'updated'?? Did I miss something??

You will see the difference in the top cell but it happens to all of them.

Before

After

Edit: Added Code

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

customCell = [_mainTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (customCell == nil)
{
    customCell = [[MNCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    CGRect frameTitle;
    frameTitle = CGRectMake(20, 4, 195, 21);

    CGRect frameSummary;
    frameSummary = CGRectMake(20, 25, 250, 30);

    CGRect frameDate;
    frameDate = CGRectMake(200, 4, 100, 21);

    MNotes *mnotes = [[self fetchedResultsController] objectAtIndexPath:indexPath];

    //Strings for Title and Summary
    titleString = mnotes.noteTitleString;
    summaryString = mnotes.mainNoteString;

    NSLog(@"TITLE STRING = %@", titleString);

    //Date
    SORelativeDateTransformer *relativeDateTransformer = [[SORelativeDateTransformer alloc] init];
    relativeDate = [relativeDateTransformer transformedValue:mnotes.createDate];

    customCell.noteTitle = [[UILabel alloc] initWithFrame:frameTitle];
    customCell.noteTitle.backgroundColor = [UIColor clearColor];
    customCell.noteTitle.font = [UIFont systemFontOfSize:20];
    customCell.noteTitle.userInteractionEnabled = NO;
    customCell.noteTitle.textColor = [self colorWithHexString:@"274D70"];

    customCell.noteSummary = [[UITextView alloc] initWithFrame:frameSummary];
    customCell.noteSummary.backgroundColor = [UIColor clearColor];
    customCell.noteSummary.font = [UIFont systemFontOfSize:10];
    customCell.noteSummary.userInteractionEnabled = NO;

    customCell.noteDate = [[UILabel alloc] initWithFrame:frameDate];
    customCell.noteDate.backgroundColor = [UIColor clearColor];
    customCell.noteDate.font = [UIFont systemFontOfSize:16];
    customCell.noteDate.userInteractionEnabled = NO;
    customCell.noteDate.textColor = [self colorWithHexString:@"274D70"]; //#274D70

}

customCell.noteTitle.text = titleString;
customCell.noteSummary.text = summaryString;
customCell.noteDate.text = relativeDate;

[customCell.contentView addSubview:customCell.noteTitle];
[customCell.contentView addSubview:customCell.noteSummary];
[customCell.contentView addSubview:customCell.noteDate];

 return customCell;
 }
jwknz
  • 6,598
  • 16
  • 72
  • 115
  • please review my edited answer. – Adam Lockhart Dec 02 '12 at 21:26
  • What is _mainTableView? Also see the new question in my response. – Adam Lockhart Dec 02 '12 at 21:42
  • _mainTableView is the TableView inside a UIViewController - I have always had a warning come up if I use a normal tableView because it gets re-defined in this method, so this change has gotten rid of the warning and never caused any issues. – jwknz Dec 02 '12 at 22:06
  • Is this a UITableViewController subclass that we are looking at? – Adam Lockhart Dec 02 '12 at 22:09
  • No a UIViewController with a TableView added to it. – jwknz Dec 02 '12 at 22:10
  • Ok I got it sussed!!! The whole problem was this: _customCell.noteTitle.backgroundColor = [UIColor clearColor]; this would have meant that it would hide the label background and see what is behind there. Hence the Double ups:-) – jwknz Dec 02 '12 at 22:29

4 Answers4

1

UITableViews work by recycling cells. When the table view requests a cell from its delegate, if there is an existing unused cell, it will use it. Otherwise it will, allocate a new one. You should only add labels when a new cell is allocated. If it is instead recycled, you only want to set the text of the existing label.


Like this:

    customCell.noteDate.textColor = [self colorWithHexString:@"274D70"]; //#274D70

    [customCell.contentView addSubview:customCell.noteTitle];
    [customCell.contentView addSubview:customCell.noteSummary];
    [customCell.contentView addSubview:customCell.noteDate];
    // try adding this:
    customCell.contentView.autoresizesSubviews = false;
}

customCell.noteTitle.text = titleString;
customCell.noteSummary.text = summaryString;
customCell.noteDate.text = relativeDate;

Note: When instantiated, the cell's content view and might be size 0,0. It could be resizing the subviews when it is given its real size.


This seemed strange... Why aren't you using the tableView that is calling the delegate? Like normal:

customCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
Adam Lockhart
  • 1,165
  • 1
  • 10
  • 13
  • I guess that my problem is that whatever I seem to put inside the block of code that you are referring to, seems to not be used in the part that I need. – jwknz Dec 02 '12 at 21:33
  • See my other post as well. Once it begins to recycle cells you will have different problems. – Adam Lockhart Dec 02 '12 at 22:31
1

This stuff needs to move out after the allocation block.:

MNotes *mnotes = [[self fetchedResultsController] objectAtIndexPath:indexPath];

//Strings for Title and Summary
titleString = mnotes.noteTitleString;
summaryString = mnotes.mainNoteString;

NSLog(@"TITLE STRING = %@", titleString);

//Date
SORelativeDateTransformer *relativeDateTransformer = [[SORelativeDateTransformer alloc] init];
relativeDate = [relativeDateTransformer transformedValue:mnotes.createDate];

This stuff really should go in your UITableViewCell subclass definition, but it can stay for now:

customCell.noteTitle = [[UILabel alloc] initWithFrame:frameTitle];
customCell.noteTitle.backgroundColor = [UIColor clearColor];
customCell.noteTitle.font = [UIFont systemFontOfSize:20];
customCell.noteTitle.userInteractionEnabled = NO;
customCell.noteTitle.textColor = [self colorWithHexString:@"274D70"];

customCell.noteSummary = [[UITextView alloc] initWithFrame:frameSummary];
customCell.noteSummary.backgroundColor = [UIColor clearColor];
customCell.noteSummary.font = [UIFont systemFontOfSize:10];
customCell.noteSummary.userInteractionEnabled = NO;

customCell.noteDate = [[UILabel alloc] initWithFrame:frameDate];
customCell.noteDate.backgroundColor = [UIColor clearColor];
customCell.noteDate.font = [UIFont systemFontOfSize:16];
customCell.noteDate.userInteractionEnabled = NO;
customCell.noteDate.textColor = [self colorWithHexString:@"274D70"]; //#274D70

[customCell.contentView addSubview:customCell.noteTitle];
[customCell.contentView addSubview:customCell.noteSummary];
[customCell.contentView addSubview:customCell.noteDate];
Adam Lockhart
  • 1,165
  • 1
  • 10
  • 13
0

What I suspect is that there is something wrong in your

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

method implementation. Can you paste the code here.

What is obvious from the description is that, you are doing [cell addSubview:label] after recycling the cell. Hence, everytime the table's cell is reloaded, instead of just setting the label's text, you are adding a subview and then setting it.

What you should do is get the cell from [tableView dequeueReusableCellWithIdentifier:@"identifier"], and only if cell is nil, perform addSubview. Otherwise, just set the subview's text

Kiran Kumar
  • 1,192
  • 8
  • 10
  • Yeah you are right, I am adding subviews - I have pasted the code – jwknz Dec 02 '12 at 20:50
  • All the setting of text should happen outside if (customCell == nil) { customCell = [[MNCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } block. Everything else related to setting layout, color etc should happen inside that block. – Kiran Kumar Dec 02 '12 at 20:53
  • That does not seem to work, I get blank cells. the addSubView needs to be outside of that block to and in return I also need alloc & init outside of that block?? – jwknz Dec 02 '12 at 21:03
  • alloc and init should be inside that block. Lines like MNotes *mnotes = [[self fetchedResultsController] objectAtIndexPath:indexPath]; //Strings for Title and Summary NSString *titleString = mnotes.noteTitleString; NSString *summaryString = mnotes.mainNoteString; customCell.noteTitle.text = titleString; customCell.noteSummary.text = summaryString; all these are the only ones outside the block (before the return) – Kiran Kumar Dec 02 '12 at 21:08
  • So I am doing what I think you are telling me - I have updated the code, but now my cells are empty. – jwknz Dec 02 '12 at 21:14
  • Everything looks right, except that the following lines also shouls be outside the block. MNotes *mnotes = [[self fetchedResultsController] objectAtIndexPath:indexPath]; //Strings for Title and Summary titleString = mnotes.noteTitleString; summaryString = mnotes.mainNoteString; NSLog(@"TITLE STRING = %@", titleString); – Kiran Kumar Dec 02 '12 at 21:18
  • ok, I have that and it still is not working. I am also puzzled why you suggest that an alloc & init is within the block and the addSubView is outside - They seem to go hand in hand. – jwknz Dec 02 '12 at 21:22
0

This problem is solved when you set a background color to your UILabel. I had it set to:

[UIColor clearColor];

This meant that I would keep seeing what happend to all previous entries.

So set it to any color e.g. [UIColor blueColor];

jwknz
  • 6,598
  • 16
  • 72
  • 115