Question

I have a UITableView that exceeds the screen region. I display some data from an NSMutableArray which is filled with NSDictionary objects. The objects all have a group property which is true or false, if group is true a UIButton should be displayed in the cell (to expand the group).
I created a UIButton in my cell prototype in storyboard. I gave it alpha 0. If I load the list the button is not in any cell (duh). This is in my cellForRowAtIndexPath:

if ([[contacts[indexPath.section] valueForKey:@"group"] isEqualToString:@"true"]) {
    UIButton *button = (UIButton*)[cell viewWithTag:999];
    [button setAlpha:1.0f];
}

If the group property is true make the button visible. In my current test case the first three objects have group set to true, the rest have group set to false. Now my problem is, the first three cells have a visible button (as intended), but some cells further along the table have one as well. I put a breakpoint in the above if statement, and it really goes in there only three times.

It happens in a pattern, the first three cells have a button, than five cells don't and than another three have a visible button. Than another five have no button and the last cell does (I think if I add two cells they will also have a button)

The second group of cells that have a button starts just outside the screen, so that may have something to do with it.

One more relevant thing, There is also some text displayed that I take from the same array as the group flag, this text is displayed correct. So it's not that the cells are duplicated somehow, it's just the if statement part that screws up.

I double checked the amount of times the program goes into the if statement and it's really only three times (the first three entries). If I comment the setAlpha call on the button no buttons appear anywhere, so there is also no other place where the button can become visible.

I'm testing on an iPad 4 with iOS 7.1.

If I decrease the height of my rows so all of them fit in the screen, the problem is gone, so It's definitely related to rows falling outside the screen region while loading the data.


edit

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = nil;
    UIColor *color = [UIColor colorWithRed:(1.0f/255.0f)*220 green:(1.0f/255.0f)*220 blue:(1.0f/255.0f)*225 alpha:1.0f];

    if (indexPath.row == 0) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"single" forIndexPath:indexPath];

        UILabel *screenname = (UILabel*)[cell viewWithTag:10];
        UILabel *username = (UILabel*)[cell viewWithTag:11];
        UIImageView *avatar = (UIImageView*)[cell viewWithTag:20];

        if ([[contacts[indexPath.section] valueForKey:@"group"] isEqualToString:@"true"]) {
            NSDictionary *c = contacts[indexPath.section];

            UIButton *button = (UIButton*)[cell viewWithTag:999];
            [button setAlpha:1.0f];

            button.tag = indexPath.section;
            [button addTarget:self action:@selector(onGroupButtonClick:) forControlEvents:UIControlEventTouchUpInside];
            int numUsersInGroup = [[c valueForKey:@"users"] count];
            NSString *numUsersInGroupString = [NSString stringWithFormat:@"%d",numUsersInGroup];
            [button setTitle:numUsersInGroupString forState:0];
            [button setNeedsDisplay];

            screenname.text = @"Groep";
            username.text = [NSString stringWithFormat:@"%@",[c valueForKey:@"groupName"]];
        } else {
            User *c = (User*)contacts[indexPath.section];

            UIButton *button = (UIButton*)[cell viewWithTag:999];
            [button setAlpha:0.0f];

            screenname.text = [NSString stringWithFormat:@"%@",[c valueForKey:@"screenName"]];
            username.text = [NSString stringWithFormat:@"%@",[c valueForKey:@"username"]];

            [avatar setImage:[UIImage imageNamed:@"avatar.png"]];
        }

        [GeneralFunctions setFontFamily:@"KozGoPro-ExtraLight" forView:cell andSubViews:YES];
        [GeneralFunctions setFontFamily:@"KozGoPro-Medium" forView:screenname andSubViews:YES];

        [cell.layer setShadowColor:[color CGColor]];
        [cell.layer setShadowOffset:CGSizeMake(0,4)];
        [cell.layer setShadowRadius:3.0f];
        [cell.layer setShadowOpacity:1.0f];
        cell.clipsToBounds = NO;
        cell.layer.masksToBounds = NO;
    }

    if (indexPath.row > 0) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"group" forIndexPath:indexPath];

        UILabel *screenname = (UILabel*)[cell viewWithTag:10];
        UILabel *username = (UILabel*)[cell viewWithTag:11];

        User *c = (User*)[contacts[indexPath.section] valueForKey:@"users"][indexPath.row-1];

        screenname.text = [NSString stringWithFormat:@"%@",[c valueForKey:@"screenName"]];
        username.text = [NSString stringWithFormat:@"%@",[c valueForKey:@"username"]];

        [GeneralFunctions setFontFamily:@"KozGoPro-ExtraLight" forView:cell andSubViews:YES];
        [GeneralFunctions setFontFamily:@"KozGoPro-Medium" forView:screenname andSubViews:YES];
    }

    return cell;
}
Was it helpful?

Solution

When your cell is reused you are not setting the button back to the 0.0 alpha. You need to reset your cell or change your cell's property whenever you reuse a cell otherwise it'll show the old content

if ([[contacts[indexPath.section] valueForKey:@"group"] isEqualToString:@"true"]) {
    NSDictionary *c = contacts[indexPath.section];

    UIButton *button = (UIButton*)[cell viewWithTag:999];
    [button setAlpha:1.0f];

    //this line changes your tag and hence in else condition for reused cell it'll come nil
    button.tag = indexPath.section;

} else {
    UIButton *button = (UIButton*)[cell viewWithTag:999];
    [button setAlpha:0.0f];
}

Suggestion instead of accessing button by tag access it by using property by type casting the cell into your custom cell

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top