【问题标题】:UITableView scrolling issueUITableView 滚动问题
【发布时间】:2011-11-20 21:21:22
【问题描述】:

我有一个带有自定义单元格的 TableView,其中一些有图像,而另一些没有。一切正常,但是当我开始滚动时,单元格显示不正确(图像被放置在“错误”的单元格中并在中间剪切)。有人现在如何解决这个问题吗?

【问题讨论】:

  • 显示细胞构造的代码会对你有所帮助。
  • 代码确实很大,但主要目的是在需要的地方添加图像并相应地编辑单元格高度。
  • 您是否在表格中使用多个部分?

标签: iphone uitableview scroll cell


【解决方案1】:

您可能会在创建单元格实例时添加图像,而不是在表格视图要求单元格视图时添加图像。示例:

这是正确的方法。每次表格视图请求单元格时,我们都会设置图像。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ident"];
    UIImageView *imageView;
    if (cell == nil) {
        cell = [UITableViewCell alloc] init ....];
        imageView = [[UIIMageView alloc] init];
        imageView.tag = 123;
        [cell addSubview:imageView];
        [imageView release];
    } else {
        imageView = [cell viewWithTag:123];
    }

    imageView.image = ...; // load image here
}

这是错误的方法。我们在创建单元格时设置图像。这将导致单元格在重复使用时出现错误的图像。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ident"];
    if (cell == nil) {
        cell = [UITableViewCell alloc] init ....];
        UIImageView *imageView = [[UIIMageView alloc] init];
        imageView.image = ...; 
        [cell addSubview:imageView];
        [imageView release];
    }

}

【讨论】:

  • 那么,如果我做对了,下一个单元格是在前一个单元格的“基础”上构建的吗?
  • 有点。表格视图只会创建适合一个屏幕所需的单元格视图。然后,当您向下滚动时,消失的顶部单元格将被重新使用并通过dequeueReusableCellWithIdentifier 添加到底部。因此,您需要确保每次调用 cellForRowAtIndexPath 时都配置单元格,而不仅仅是在创建单元格视图时。
【解决方案2】:

要理解的关键是您的表格单元格被重复使用。这样做是为了提高滚动性能,因为创建一个新单元格(即视图)非常昂贵。

在方法 cellForRowAtIndexPath 中,您返回一个单元格。使用 dequeue 方法的现有单元格,或者创建一个新单元格。在该单元格上,您可以设置要表示的任何内容的所有属性。

我的猜测是您直接在单元格上设置这些属性,例如图像等。然后,当您滚动时,该单元格会被重复使用,您会再次看到相同的图像,但在错误的单元格上。

因此,您需要一个单独的索引(如 NSArray)来维护您的模型对象。该模型对象包含图像的所有细节等。

让我们举个例子。我有一个包含 10 个对象的数组,其中前五个是图像“a.png”,后五个是“b.png”。

如果我收到 cellForRowAtIndexPath 的回调,我想这样做:

cellForRowAtIndexPath:(0,0) 为数组中的对象提供索引 0,即 a.png cellForRowAtIndexPath:(0,1) 提供数组中的对象索引 1,即 a.png cellForRowAtIndexPath:(0,2) 提供来自数组索引 2 的对象,即 a.png cellForRowAtIndexPath:(0,3) 提供来自数组索引 3 的对象,即 a.png cellForRowAtIndexPath:(0,4) 提供数组中的对象索引为 4,即 a.png cellForRowAtIndexPath:(0,5) 提供数组中的对象索引为 5,即 b.png cellForRowAtIndexPath:(0,6) 提供数组中的对象 a 索引 6,即 b.png cellForRowAtIndexPath:(0,7) 提供数组中的对象索引为 7,即 b.png cellForRowAtIndexPath:(0,8) 提供数组中的对象索引为 8,即 b.png cellForRowAtIndexPath:(0,9) 为数组中的对象提供索引 9,即 b.png

现在,让我们考虑在 UITableView 中,在幕后,五个单元格正在被重用。

对于上面的每个调用,都会发生以下情况:

cellForRowAtIndexPath:(0,1) 为数组中的对象提供索引 1,即 a.png -- 您尝试将现有单元格出列,但它返回“nil”,因此您创建了一个新单元格。您设置模型对象的详细信息。

cellForRowAtIndexPath:(0,2) 提供来自数组索引 2 的对象,即 a.png -- 您尝试将现有单元格出列,但它返回“nil”,因此您创建了一个新单元格。您设置模型对象的详细信息。

cellForRowAtIndexPath:(0,3) 提供来自数组索引 3 的对象,即 a.png -- 您尝试将现有单元格出列,但它返回“nil”,因此您创建了一个新单元格。您设置模型对象的详细信息。

cellForRowAtIndexPath:(0,4) 为数组中的对象提供索引 4,即 a.png -- 您尝试将现有单元格出列,但它返回“nil”,因此您创建了一个新单元格。您设置模型对象的详细信息。

cellForRowAtIndexPath:(0,5) 提供数组中的对象索引为 5,即 b.png -- 您尝试将现有单元格出列并且它有效!您可以通过设置模型对象的详细信息再次使用该单元格

cellForRowAtIndexPath:(0,6) 提供来自数组索引 6 的对象,即 b.png -- 您尝试将现有单元格出列并且它有效!您可以通过设置模型对象的详细信息再次使用该单元格

cellForRowAtIndexPath:(0,7) 提供来自数组索引 7 的对象,即 b.png -- 您尝试将现有单元格出列并且它有效!您可以通过设置模型对象的详细信息再次使用该单元格

cellForRowAtIndexPath:(0,8) 提供数组中的对象索引为 8,即 b.png -- 您尝试将现有单元格出列并且它有效!您可以通过设置模型对象的详细信息再次使用该单元格

cellForRowAtIndexPath:(0,9) 为数组中的对象提供索引 9,即 b.png -- 您尝试将现有单元格出列并且它有效!您可以通过设置模型对象的详细信息再次使用该单元格

抱歉这么啰嗦!我希望这有帮助。也许值得通过一个好的表格视图教程来学习。肯定会有很多。

【讨论】:

  • 哎呀,我犯了一些数组索引错误。现在在上面的编辑中解决了。对不起!
【解决方案3】:

尝试更改单元格的标识符值。

NSString* identifierStr = [NSString stringWithFormat:@"ident_%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifierStr];

【讨论】:

    猜你喜欢
    • 2011-11-24
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2013-08-01
    • 2011-03-15
    • 1970-01-01
    相关资源
    最近更新 更多