denikov
denikov

Reputation: 869

uitableview with multiple custom cells scrolling and reusing issue

I've seen this question asked a lot but haven't found a good example for what I need. Everywhere people specify that row 0 needs to be this cell, row 1 needs to be that cell, and others something else.

I need to differentiate my cells based on the data. Lets say this is what my NSMutableArray of dictionaries looks like:

{(
  actionContent = "some comment",
  actionType = "comment",
  datetime = "some date",
  whosAction = "some person"
),
(
  actionContent = "",
  actionType = "like",
  datetime = "some date", 
  whosAction = "another person"
),
(
  actionContent = "blah blah blah mentioned you",
  actionType = "mention",
  datetime = "some date",
  whosAction = "person"
)}

Something like that, I know the syntax is probably way off. So for this I have created two custom cells and in the cellForRowAtIndexPath I run a bunch of if statements to see which cell to use. First cell has only one UITextView and it is for likes, Second cell has two UITextViews and it's for comments and mentions.

THE PROBLEM: As I scroll the table, the Second cell comes into view and I get this error (all UITextViews have tap gestures):

-[FirstCell secondTap]: unrecognized selector sent to instance 0xa872020

FirstCell doesn't have a "second" UITextView so there shouldn't be any secondTap...so apparently I'm using the multiple cells wrong in the cellForRowAtIndexPath. I'll show my code now:

FirstCell:

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
    UITextView *first = [[UITextView alloc]initWithFrame:CGRectMake(55, 15, 250, 20)];
    [first setFont:[UIFont systemFontOfSize:10]];
    [first setTextColor:[UIColor blueColor]];
    [first setEditable:NO];
    [first setScrollEnabled:NO];
    [first setSelectable:YES];
    [first setUserInteractionEnabled:YES];
    [first setAllowsEditingTextAttributes:YES];
    first.textContainerInset = UIEdgeInsetsMake(3, 0, 0, 0);
    UITapGestureRecognizer *firstTap = [[UITapGestureRecognizer alloc]init];
    _firstTap = firstTap;
    [first addGestureRecognizer:_firstTap];
    [self addSubview:_first];
}

SecondCell:

//same _first UITextView and a second one
    UITextView *first...

    UITextView *second = [[UITextView alloc]initWithFrame:CGRectMake(55, 20, 250, 30)];
    [second setFont:[UIFont systemFontOfSize:10]];
    [second setEditable:NO];
    [second setScrollEnabled:NO];
    [second setSelectable:YES];
    [second setUserInteractionEnabled:YES];
    [second setAllowsEditingTextAttributes:YES];
    second.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
    UITapGestureRecognizer *secondTap = [[UITapGestureRecognizer alloc]init];
    _secondTap = secondTap;
    [second addGestureRecognizer:_secondTap];
    _second = second;
    [self addSubview:_second];

I'm sure the problem is somewhere here...cellForRowAtIndexPath:

static NSString *cellIdentifier = @"cell";
if (myData.count != 0) {
    if ([[[myData objectAtIndex:indexPath.section]valueForKey:@"actionContent"]isEqualToString:@""]) {
        FirstCell *cell = (FirstCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (!cell) {
            cell = [[FirstCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }
        //run if statements to checks if this is a likes or friend requests
        return cell;
    }else{
        SecondCell *cell = (SecondCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (!cell){
            cell = [[SecondCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }
        //run if statements to check if comments or mentions
        return cell;
    }
}else{
    //use FirstCell to display empty message
}
return nil;

I hope that wasn't too lengthy and I hope I was clear. I think I'm initializing them wrong. Any advice how to make this work?

BTW: I used this example but as I said, they had they rows already set up, they knew which row should be which cell. I need to always check.

Upvotes: 0

Views: 778

Answers (2)

Kujey
Kujey

Reputation: 1122

I think your problem is that you didn't override the PrepareForReuse Methode in your UITableViewCell subclasses.

You need to clean those UITextView you inserted before reuse. Else they are added again and again on reuse.

Like that :

-(void)prepareForReuse
{
    [super prepareForReuse];

    [self.first removeFromSuperview];
    self.first = nil;

    [self removeGestureRecognizer:self.firstTap];
    self.firstTap = nil;
}

Also you should have two different identifiers for your cells. To do so, you have to insert those lines once your tableView is instantiated :

[self.tableView registerClass:[FirstCell class] forCellWithReuseIdentifier:@"firstCell"];
[self.tableView registerClass:[SecondCell class] forCellWithReuseIdentifier:@"secondCell"];

And then you use these identifiers in the cellForRow method

Upvotes: 2

TylerP
TylerP

Reputation: 9829

You're using the same cell identifier ("cell") for two different cell types. Try giving your FirstCell an identifier of something like @"firstCell" and your second one an identifier like @"secondCell".

Upvotes: 4

Related Questions