简体   繁体   中英

UITableViewCell subview not being displayed when the table is first displayed

I am trying to add a strikethrough label to my table cells (conditional on a BOOL hasStrikethrough). The problem is that the strikethrough does not appear when the table is first displayed (even though hasStrikethrough == YES). If you scroll the table then the rows get redisplayed and the strikethrough appears correctly. The strikethrough is just a UILabel that is being added as a subview of the UITableViewCell.

Here is my code for cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *CellIdentifier = @"ItemCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell==nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}


Item  *item = [self.fetchedResultsController objectAtIndexPath:indexPath];

cell.textLabel.text = item.itemName;
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.showsReorderControl = YES;
cell.shouldIndentWhileEditing = NO;

if ([[item hasStrikethrough] boolValue] == YES) {
    [self addStrikethrough:cell];
}

return cell;
}

Here is the code for addStrikethrough:

- (void)addStrikethrough:(UITableViewCell*)cell
{
CGRect frame = cell.textLabel.frame;
UILabel *strikethrough = [[UILabel alloc] initWithFrame:frame];
strikethrough.opaque = YES;
strikethrough.backgroundColor = [UIColor clearColor];
strikethrough.text = @"------------------------------------------------";
strikethrough.lineBreakMode = UILineBreakModeClip;
[cell addSubview:strikethrough];
}

Thanks in advance :-)

The problem is with the line CGRect frame = cell.textLabel.frame;
The cell's textLabel didn't laid out yet, so the frame will be (0,0,0,0) and u won't see the strikethrough label.

The reason u see the strikethrough in the next cells is because those are the reused cells that already laid out the textLabel.

As I see it u have two options:
First option, set the strikethrough frame yourself, u can use sizeWithFont to figure out what is the needed width, the font should be the textFiled font. Play with it a bit to find the correct x offset so it will be exactly on the textLabel.

- (void)addStrikethrough:(UITableViewCell*)cell
{
    CGSize textLabelSize = [cell.textLabel.text sizeWithFont:[UIFont systemFontOfSize:20.0]];

    CGFloat cellHeight = cell.bounds.size.height;
    CGFloat strikethroughLabelHeight = 20.0;

    CGRect frame = CGRectMake(12, (cellHeight - strikethroughLabelHeight)/2, textLabelSize.width, strikethroughLabelHeight);
    UILabel *strikethrough = [[UILabel alloc] initWithFrame:frame];
    strikethrough.opaque = YES;
    strikethrough.backgroundColor = [UIColor clearColor];
    strikethrough.text = @"------------------------------------------------";
    strikethrough.lineBreakMode = UILineBreakModeClip;
    [cell.contentView addSubview:strikethrough];
}  

Second option is to subclass UITableViewCell and add the strikethrough label to it.
then u can set it's frame in layoutSubviews method, and u can hide/unhide this label according to your needs...

The cell is reused based on its reuse identifier. Currently you're only using one identifier so "cell with no subview" looks the same as "cell with subview" to the OS.

Try checking the strikethrough condition at the beginning, and inventing a new reuse identifier (eg StrikeIdentifier ) in that case.

Here is one approach that does what I'm suggesting:

Item *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
BOOL isStrike = ([[item hasStrikethrough] boolValue]);

static NSString *CellIdentifier = @"ItemCell";
static NSString *StrikeIdentifier = @"ItemCellStrike";

UITableViewCell *cell = (isStrike)
                        ? [tableView dequeueReusableCellWithIdentifier:StrikeIdentifier]
                        : [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell==nil) {
    if (isStrike) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:StrikeIdentifier];
        [self addStrikethrough:cell];
    } else {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
}

. . .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM