Check if UIButton already exists on UITableViewCel

2019-08-30 10:10发布

问题:

For every UITableViewCell I'm creating a UIButton in the tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath method. I want to check if UIButton is already there when creating it, so it's not added multiple times, but I can't. Here's my code:

- (UITableViewCell *)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

        UIImageView *cellBottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, CELL_HEIGHT, 320.0, 1)];
        cellBottomLine.image = [UIImage imageNamed:@"bottomCellImage.png"];
    if (cellBottomLine.subviews) {
        [cell addSubview:cellBottomLine];
    }

        copyButton = [BSFunctions createButtonWithNormalImageNamed:@"copyCellButton.png" highlightedImageName:@"copyCellButtonPressed.png" target:self selector:@selector(copyPressedFromCell:)];
        [copyButton setFrame:CGRectMake(250, 10, 62, 32.5)];
        copyButton.tag = indexPath.row;
    if (!copyButton.superview) {
        [cell addSubview:copyButton];
    }

    return cell;
}

回答1:

- (UITableViewCell *)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
     UIImageView *cellBottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, CELL_HEIGHT, 320.0, 1)];
cellBottomLine.image = [UIImage imageNamed:@"bottomCellImage.png"];
    if (cellBottomLine.subviews) 
    {
        [cell addSubview:cellBottomLine];
    }

    for (UIView *view in [cell subviews]) 
    {
        if ([view isKindOfClass:[UIButton class]]) 
        {
             return cell;
        }
    }

    copyButton = [BSFunctions createButtonWithNormalImageNamed:@"copyCellButton.png"
                                          highlightedImageName:@"copyCellButtonPressed.png"
                                                        target:self
                                                      selector:@selector(copyPressedFromCell:)];
    [copyButton setFrame:CGRectMake(250, 10, 62, 32.5)];
    copyButton.tag = indexPath.row;
    if (!copyButton.superview)
    {
        [cell addSubview:copyButton];
    }

    return cell;
}


回答2:

I think you should use cellForRowAtIndexPath method for adding any subviews to cell, so that the cell will be reused when scrolling back and forth and you dont require any check before adding subviews to cell.



回答3:

Stavash's answer is the best, but if you don't want to do that, alternatively you can use tableView:cellForRowAtIndexPath:. I saw that you tried that and that the state of the button was lost while scrolling. I assume this is due to cell reuse. With cell reuse, once a table view cell goes off the screen, it is cached with an identifier and then the next cell to come on the screen retrieves a cell with a given identifier from the cache.

To avoid the button losing its state when it goes off the screen, you can use multiple reuse identifiers and store the states of your buttons in an array. We'll call this property buttonStates (it should be a mutable array).

Initialize your buttonStates variable and add strings to represent "base states." Add as many of these strings as the number of cells in your table (I assume there is only one section based on your code).

When the state changes (this would probably happen in your copyPressedFromCell: method, update the object at the index of the button's tag (which you have already set to the index of the cell) with a string representing the new state.

With all that done, make your cellForRowAtIndexPath: method looks like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *CellIdentifier = self.buttonStates[indexPath.row];
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

Before we continue lets take a look at some of your willDisplayCell: code (which should be moved here).

UIImageView *cellBottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, CELL_HEIGHT, 320.0, 1)];
cellBottomLine.image = [UIImage imageNamed:@"bottomCellImage.png"];
if (cellBottomLine.subviews) {
    [cell addSubview:cellBottomLine];
}

Why are you running that if statement? If you've just created a new image view, it's going to return YES every time (assuming that the array of subviews is not nil by default). You would rather check if a bottom cell image already exists within the cell's subviews. But we don't even need to do that. Just add the image in the cellForRowAtIndexPath: method, inside the !cell if. That way, we only add the bottomCellImage if the cell hasn't been created yet.

The same thing goes for your if (!copyButton.superview) call. Continuing where we left of in our cellForRowAtIndexPath: method:

        UIImageView *cellBottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, CELL_HEIGHT, 320.0, 1)];
        cellBottomLine.image = [UIImage imageNamed:@"bottomCellImage.png"];
        [cell addSubview:cellBottomLine];

        copyButton = [BSFunctions createButtonWithNormalImageNamed:@"copyCellButton.png"
                                      highlightedImageName:@"copyCellButtonPressed.png"
                                                    target:self
                                                  selector:@selector(copyPressedFromCell:)];
        [copyButton setFrame:CGRectMake(250, 10, 62, 32.5)];
        copyButton.tag = indexPath.row;
        [cell addSubview:copyButton];
    }

    UIButton *button = [cell viewWithTag:indexPath.row]; // Get the copy button
    // Update the state of the button here based on CellIdentifier, outside the if statement so that it gets updated no matter what
    // Also configure your cell with any non-button related stuffs here

    return cell;
}


回答4:

To avoid this altogether, why not subclass UITableViewCell and create a designated representation of that class in a storyboard/XIB? That way, when cells are reused, the OS will not create the UI elements again and again but rather reuse the ones that were already allocated from IBOutlets.



回答5:

you can check it in this way:
1) put somewhere `copyButton = nil;` (in viewDidLoad, or somewhere else;
2) then:
- (UITableViewCell *)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

        UIImageView *cellBottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, CELL_HEIGHT, 320.0, 1)];
        cellBottomLine.image = [UIImage imageNamed:@"bottomCellImage.png"];
    if (cellBottomLine.subviews) {
        [cell addSubview:cellBottomLine];
    }
    if (!copyButton) {
        copyButton = [BSFunctions createButtonWithNormalImageNamed:@"copyCellButton.png" highlightedImageName:@"copyCellButtonPressed.png" target:self selector:@selector(copyPressedFromCell:)];
        [copyButton setFrame:CGRectMake(250, 10, 62, 32.5)];
        copyButton.tag = indexPath.row;
        if (!copyButton.superview) {
           [cell addSubview:copyButton];
        }
     }

    return cell;
}


回答6:

Try in the following way

if ([cell viewWithTag:LBL_TAG])
{
    UIView *vi = (UIView*)[cell viewWithTag:LBL_TAG];
    if ([vi isKindOfClass:[UILabel class]])
    {
        UILabel *lbl = (UILabel*)vi;
        NSLog(@"test  %@..",lbl.text);
    }
}

Hope it may help you.