Iphone iOS UILabel未重新绘制为新大小

Iphone iOS UILabel未重新绘制为新大小,iphone,objective-c,ios,uitableview,uilabel,Iphone,Objective C,Ios,Uitableview,Uilabel,我有一组UILabel,它们显示在TableView的单元格中。当用户触摸单元格时,标签将展开以显示我输入的所有文本,而不是两行截断的文本 动画和展开工作正常,但当我再次按下标签使其收缩TableViewCell时,标签处于正确的大小,但标签没有。我已经记录了标签的大小,并且通过编程我的代码可以工作,但无法正确绘制 以下是我的cellForRowAtIndexPath方法: - (UITableViewCell *) tableView:(UITableView *)tableView cell

我有一组UILabel,它们显示在TableView的单元格中。当用户触摸单元格时,标签将展开以显示我输入的所有文本,而不是两行截断的文本

动画和展开工作正常,但当我再次按下标签使其收缩TableViewCell时,标签处于正确的大小,但标签没有。我已经记录了标签的大小,并且通过编程我的代码可以工作,但无法正确绘制

以下是我的cellForRowAtIndexPath方法:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];

    UILabel *label = nil;
    int noOfLines;

    UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];
    label = [[UILabel alloc] initWithFrame:CGRectZero];

    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

    label.text = contentForRow;
    if ([expandedIndexPathsArray containsObject:indexPath])
        {
        noOfLines = 0;
        CGSize size = [contentForRow sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
        label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f));
        NSLog(@"height is now %f",label.frame.size.height);
    } else {
        noOfLines = 2;
        CGSize size = [contentForRow sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
        label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MIN(size.height, 44.0f));
         NSLog(@"height is now %f",label.frame.size.height);
    }
    NSLog(@"Number of Lines: %d",noOfLines);
    label.lineBreakMode = UILineBreakModeWordWrap;
    label.backgroundColor = [UIColor blueColor];
    label.font = [UIFont systemFontOfSize:FONT_SIZE];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    label.numberOfLines = noOfLines;
    [[cell contentView] addSubview:label];
    [label release];
    return cell;
}
谁能告诉我这里发生了什么,因为我正在努力理解它


提前谢谢!:D

您发布的代码不会出现(根据您的评论)将新标签分层到旧标签上。但是,每次调用该方法时,它都会创建一个全新的单元格。这不是通常的设计模式

通常的模式是回收单元,只有在回收单元不可用时才创建新单元。使用这种方法,您确实需要(根据您的评论)某种方式来跟踪标签。(下面的代码段中显示了一种方法。)

您尚未发布tableView:heightForRowAtIndexPath:method。根据发生的情况,您可能会出现奇怪的行为,即如果行高度与标签高度不匹配。在tableView上调用重新加载数据(或相关方法)的时间也不清楚。这确实需要调用,以便iOS可以刷新单元格行高度。也许这在你的代码中是可以的,但绝对值得检查

我已经测试了以下代码,它以我认为您在问题中试图实现的方式扩展和减少了单元格。为了方便起见,这段代码只是测试行是否与给定的数字匹配,以确定它是否展开。您将用[expandedIndexPathsArray containsObject:indexPath]替换我的([indexPath行]==\u pgSpecialRow)

我通过添加两个额外的方法(尽管这里的代码总数较少)将工作分开。这部分是为了帮助可读性,部分是因为tableView:heightforrowatinexpath:方法需要与tableView:cellforrowatinexpath:方法进行相同的求和

- (UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* cellIdentifier = @"Cell";

    // see if there's a cell available to recylce
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell)
    {
        // there's no cell to recycle, so make a new one
        // add a label to it and tag the label so we can find it later

        cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier];
        UILabel* label = [[UILabel alloc] init];

        // do set up on label that doesn't vary with cell content
        [label setTag: 101];
        label.lineBreakMode = UILineBreakModeWordWrap;
        label.backgroundColor = [UIColor blueColor];
        label.font = [UIFont systemFontOfSize:FONT_SIZE];

        [[cell contentView] addSubview:label];
        [label release];
    }

    // either on a recycled cell or on the cell just created, set the contents

    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];
    UILabel* label = (UILabel*)[[cell contentView] viewWithTag:101];

    [self adjustLabel: label forText:contentForRow andExpanded:([indexPath row] == _pgSpecialRow)];

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

- (void) adjustLabel: (UILabel*) label forText: (NSString*) text andExpanded: (BOOL) expanded;
{    
    label.text = text;

    CGFloat height = [self heightForLabelWithText: text expanded: expanded];
    label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), height);

    label.numberOfLines = expanded ? 0: 2;
}


- (CGFloat) heightForLabelWithText: (NSString*) text expanded: (BOOL) expanded;
{
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

    if (expanded)
    {
        return MAX([text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap].height, 44.0);
    }

    return MIN([text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap].height, 44.0);
}


- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];

    // return a cell height that's big enough (with a bit of extra margin)
    return [self heightForLabelWithText: contentForRow expanded:([indexPath row] == _pgSpecialRow)]+ 16.0;
}

好的,我发现我的cellForRowAtIndexPath实际上是在旧标签的基础上添加新标签,而没有先删除它们。我是否需要以某种方式编辑已经存在的标签,或者删除其子视图并添加新的子视图?这会发生在CellForRowatineXpath还是DidSelectRowatineXpath中?谢谢Matthew,你的代码对我来说非常有用。我不得不稍微修改一下我的didSelectRowAtIndexPath方法,但现在它工作得很好。我不得不承认,我花了几个小时的时间来工作,并且理解你的代码发生了什么以及为什么,但我现在明白了。感谢您抽出时间回复!非常感谢D