iOS - heightForRowAtIndexPath 在滚动期间不会触发

Posted

技术标签:

【中文标题】iOS - heightForRowAtIndexPath 在滚动期间不会触发【英文标题】:iOS - heightForRowAtIndexPath does not fire during scrolling 【发布时间】:2011-09-28 02:44:19 【问题描述】:

我正在使用 Xcode4 编写一个简单的 ios 应用程序,它使用表格视图来显示故事列表(从 URL 获取)。我将故事标题显示为 UILabel,并显示为表格单元格的子视图。

我正在覆盖heightForRowAtIndexPath,以根据每个故事标题的长度计算单元格的正确高度。我将标签添加到cellForRowAtIndexPath 中的单元格。当我在模拟器中运行应用程序时,一切都很好。但是:当我向下滚动和向上滚动时,标签会变得混乱。它们被截断并溢出。我调试了一下,发现滚动过程中没有触发heightForRowAtIndexPath方法,所以没有重新计算单元格高度,因此标签文本溢出,变得难看。以下是相关代码:

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

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        [cell autorelease];
    

    /* NOTE: code to load trimmedTitle dynamically is snipped */
    NSString* trimmedTitle;

    UIFont *cellFont = [UIFont fontWithName:@"Georgia" size:14.0];
    CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
    CGSize labelSize = [trimmedTitle sizeWithFont:cellFont constrainedToSize:constraintSize 
                                    lineBreakMode:UILineBreakModeWordWrap];

    UILabel* tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 0, 230, labelSize.height)];
    tempLabel.lineBreakMode = UILineBreakModeWordWrap;
    tempLabel.text = trimmedTitle;
    tempLabel.numberOfLines = 0;

    [cell.contentView addSubview:tempLabel];
    [tempLabel release];

    return cell;


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    NSString* cellText;  // code to load cellText dynamically is snipped off
    UIFont *cellFont = [UIFont fontWithName:@"Georgia" size:14.0];
    CGSize constraintSize = CGSizeMake(230.0f, MAXFLOAT);
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + 20;

【问题讨论】:

可能你没有设置你的委托。 @Daniel:你能解释一下你的意思吗? 表格视图有两个“代表”。一个包含 cellForRowAtIndexPath,另一个包含 heightForRowAtIndexPath。当然,它们可以是同一个对象,但必须分别设置。 【参考方案1】:

在这种情况下,我通常会预先计算所有行的高度,将它们存储在一个数组中,然后在 heightForRowAtIndexPath 中返回这些高度。这样,表格视图就知道每个单元格的高度,并且单元格即使在重用后也符合该高度。除了查找单元格何时可见并重新加载之外,我不知道有什么方法可以强制计算单元格高度,这似乎太昂贵了。

更新:一些示例代码:

我有一个名为- (void)calculateHeights 的方法,它执行与heightForRowAtIndexPath 中相同的计算,但将结果存储在我的可变数组heights_ ivar 中:

- (void)calculateHeights 
    [heights_ removeAllObjects]
    for (Widget *myWidget in modelWidgetArray) 
        NSString* cellText;  // code to load cellText dynamically is snipped off
        UIFont *cellFont = [UIFont fontWithName:@"Georgia" size:14.0];
        CGSize constraintSize = CGSizeMake(230.0f, MAXFLOAT);
        CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

        [heights_ addObject:[NSNumber numberWithFloat:labelSize.height + 20.0f]];
    

然后在heightForRowAtIndexPath 中,给定一个 1-section 表视图:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    return [heights_ objectAtIndex:[indexPath row]];

如果您的表格视图有多个部分,您需要做一些数学运算才能转换为一维 heights_ 数组并再次返回。此外,无论何时您-reloadData,您也需要-calculateHeights

【讨论】:

如果我采用预先计算和存储行高的方法,我该如何改变单元格的高度。一点点示例代码会很有帮助。【参考方案2】:

-tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 方法在滚动视图合成之前被调用。

在调用-tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath之前调用该方法而不在滚动过程中触发的目的是表格视图(继承自UIScrollView)需要知道contentView的整个高度。一旦表格视图知道所有高度,它会在您调用 -reloadData 之前缓存高度

您的问题意味着您需要清除单元格的-prepareForReuse 中的内容并调用-setNeedLayout 来布局所有新内容。

【讨论】:

【参考方案3】:

您可以使用 tag 作为您的标签,以避免相互混淆

UILabel *label= (UILabel*)[cell viewWithTag:2];
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;

【讨论】:

以上是关于iOS - heightForRowAtIndexPath 在滚动期间不会触发的主要内容,如果未能解决你的问题,请参考以下文章

{python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO

IO模型--阻塞IO,非阻塞IO,IO多路复用,异步IO

IO复用阻塞IO非阻塞IO同步IO异步IO

四种IO模型‘阻塞IO/非阻塞IO/信号驱动IO/异步IO‘

5种IO模型阻塞IO和非阻塞IO同步IO和异步IO

网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO