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;
}
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.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:Before we continue lets take a look at some of your
willDisplayCell:
code (which should be moved here).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 notnil
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 thecellForRowAtIndexPath:
method, inside the!cell
if. That way, we only add thebottomCellImage
if the cell hasn't been created yet.The same thing goes for your
if (!copyButton.superview)
call. Continuing where we left of in ourcellForRowAtIndexPath:
method:Try in the following way
Hope it may help you.
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.