Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 是否有方法更新单个UITableViewCell的高度,而不重新计算每个单元格的高度?_Ios_Objective C_Uitableview - Fatal编程技术网

Ios 是否有方法更新单个UITableViewCell的高度,而不重新计算每个单元格的高度?

Ios 是否有方法更新单个UITableViewCell的高度,而不重新计算每个单元格的高度?,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我有一个带有几个不同部分的UITableView。一个部分包含当用户在UITextView中键入文本时将调整大小的单元格。另一部分包含呈现HTML内容的单元格,因此计算高度相对昂贵 现在,当用户输入UITextView时,为了让表视图更新单元格的高度,我调用 [self.tableView beginUpdates]; [self.tableView endUpdates]; 但是,这会导致表格重新计算表格中每个单元格的高度,而我实际上只需要更新键入的单个单元格。不仅如此,它没有使用table

我有一个带有几个不同部分的UITableView。一个部分包含当用户在UITextView中键入文本时将调整大小的单元格。另一部分包含呈现HTML内容的单元格,因此计算高度相对昂贵

现在,当用户输入UITextView时,为了让表视图更新单元格的高度,我调用

[self.tableView beginUpdates];
[self.tableView endUpdates];
但是,这会导致表格重新计算表格中每个单元格的高度,而我实际上只需要更新键入的单个单元格。不仅如此,它没有使用
tableView:estimatedHeightForRowAtIndexPath:
重新计算估计高度,而是为每个单元格调用
tableView:heightForRowAtIndexPath:
,即使这些单元格没有显示

有没有办法要求表视图只更新单个单元格的高度,而不做所有这些不必要的工作

更新

我仍在寻找解决办法。正如所建议的,我已经尝试过使用
重新加载rowsatindexpaths:
,但这似乎不起作用。调用
reloadRowsAtIndexPaths:
即使只有一行,仍会导致为每一行调用
heightForRowAtIndexPath:
,即使只为您请求的行调用
cellForRowAtIndexPath:
。事实上,看起来每当插入、删除或重新加载行时,表单元格中的每一行都会调用
heightforrowatinexpath:

我还尝试将代码放入
willDisplayCell:forrowatinexpath:
中,以计算单元格即将出现之前的高度。为了使其工作,我需要在计算后强制表视图重新请求行的高度。不幸的是,调用
[self.tableView beginUpdates];[self.tableView endUpdates]willDisplayCell:forRowAtIndexPath:
的代码在UITableView的内部代码深处导致索引越界异常。我想他们不希望我们这样做


我忍不住觉得这是SDK中的一个bug,在响应
[self.tableView endUpdates]
时,它不会为不可见的单元格调用
estimatedHeightForRowAtIndexPath:
,但我仍在尝试找到某种解决方法。感谢您的帮助。

使用以下UITableView方法:

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
必须指定要重新加载的nsindepath的NSArray。如果只想重新加载一个单元格,那么可以提供一个只包含一个nsindepath的NSArray

NSIndexPath* rowTobeReloaded = [NSIndexPath indexPathForRow:1 inSection:0];
NSArray* rowsTobeReloaded = [NSArray arrayWithObjects:rowTobeReloaded, nil];
[UITableView reloadRowsAtIndexPaths:rowsTobeReloaded withRowAnimation:UITableViewRowAnimationNone];

如上所述,
reloadRowsAtIndexPaths:withRowAnimation:
只会导致表视图向其
UITableViewDataSource
请求新的单元格视图,而不会向
UITableViewDelegate
请求更新的单元格高度

很遗憾,只有通过调用以下命令才能刷新高度:

[tableView beginUpdates];
[tableView endUpdates];
即使两次通话之间没有任何变化

如果计算高度的算法太耗时,可能应该缓存这些值。 比如:

- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat height = [self cachedHeightForIndexPath:indexPath];

    // Not cached ?
    if (height < 0)
    {
        height = [self heightForIndexPath:indexPath];
        [self setCachedHeight:height
                 forIndexPath:indexPath];
    }

    return height;
}
-(CGFloat)表视图:(UITableView*)表视图
heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
CGFloat height=[self-cachedHeightForIndexPath:indexPath];
//没有缓存?
如果(高度<0)
{
高度=[self-heightForIndexPath:indexPath];
[自行设置缓存高度:高度
forIndexPath:indexPath];
}
返回高度;
}
并确保在内容更改时或在初始时间将这些高度重置为
-1

编辑:

此外,如果您希望尽可能延迟高度计算(直到滚动到),则应尝试实现此功能(仅限iOS 7+):

@属性(非原子)CGFloat估计值

提供行高度的非负估计值可以提高 加载表视图的性能。如果表中包含变量 高度行时,计算它们的所有高度可能会很昂贵 桌子上满是东西。使用估算允许您推迟部分成本 从加载时间到滚动时间的几何计算

默认值为0,这意味着没有估计值


可变行高度对表视图性能有非常负面的影响。您所说的是在某些单元格中显示的web内容。如果我们不是在讨论数千行,考虑用UIWebView而不是UITableView实现您的解决方案可能是值得考虑的。我们也遇到了类似的情况,使用了带有自定义生成HTML标记的UIWebView,它工作得非常出色。您可能知道,当您有一个包含web内容的动态单元格时,您会遇到一个严重的异步问题:

  • 设置单元格内容后,必须
  • 等待单元格中的web视图渲染完web内容
  • 然后,您必须进入UIWebView,并使用JavaScript询问HTML文档它有多高
  • 然后更新UITableViewCell的高度
一点也不好玩,用户会有很多跳跃和紧张

如果必须使用UITableView,则一定要缓存计算出的行高。这样,以
高度返回它们将非常便宜,因为它位于索引路径:
。与其告诉UITableView该做什么,不如让数据源更快

有办法吗? 答案是否定的

对此,您只能使用heightForRowAtIndexPath。
因此,您所能做的就是尽可能降低成本,例如,在数据模型中保留一个单元格高度的NSMUTABLE数组。

始终会调用方法
heightforrowatinexpath:
,但我建议使用一种变通方法

每当用户在
UITextView中键入时
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...

    [textView setDelegate:self];
    [textView setTag:indexPath.row];

    ...
}
- (void)textViewDidChange:(UITextView *)textView
{
    savedIndexPath = [NSIndexPath indexPathForRow:textView.tag inSection:0];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (savedIndexPath != nil) {
        if (savedIndexPath == indexPath.row) {
            savedIndexPath = nil;

            // return the new height
        }
        else {

            // return cached value
        }
    }
    else {
        // your normal calculating methods...
    }
}