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;
}
- (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;
}
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:
- (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;
}
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.
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;
}
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.