5

首先要说我已经看到了这些问题:

iOS:UITableView 在滚动太快时混淆数据

(自定义)UITableViewCell 在滚动后混在一起

在 UITableView 中滚动后项目混淆

第一个和最后一个似乎与我的问题非常相关,但是我相当确定每个部分都有逻辑来确定单元格(数据)中应该出现的内容,但它们仍然混淆了。

以下是相关代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Note: the if (cell == nil) thing is no longer required in iOS 6
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}


if (closestRenter != nil)
{
    NSLog(@"CLOSEST RENTER!");
    [self setupCellsWithClosestRenterCell:cell atIndexPath:indexPath];
}
else
{
    NSLog(@"NO CLOSEST RENTER");
    [self setupCellsWithNoClosestRenterCell:cell atIndexPath:indexPath];
}

if (indexPath.section == 0)
{
    for (UIView *view in cell.contentView.subviews)
    {
        NSLog(@"WHAT THE HECK");
        [view removeFromSuperview];
    }
}

return cell;

}

相关信息在这里:

1) ClosestRenter 不是零……它存在。所以永远不应该执行 else 子句……就是这样。

2)在代码中:

[self setupCellsWithClosestRenterCell:cell atIndexPath:indexPath];

有一个简单的:

if (indexPath.section == 0)
{
    cell.textLabel.text = @"PLACE HOLDER";
}
else
{
    // Populate the cell with data. (creates a view (with controller etc) and loads it into the cell)
}

3) 始终有 2 个部分。

问题是第 0 节(第一节)应该只有那个占位符字符串。第 1 节应该包含我的自定义子视图(在单元格中,它确实如此)。

第 0 部分最初只有占位符字符串,但是一旦我向下滚动(并且该部分不再可见)并向上滚动(快速),它有时会从第 1 部分中出现看似随机的单元格......这到底是什么?如何?我不愿意责怪细胞重用,但在这一点上,除了一些非常愚蠢的事情之外,我不知道它是什么。

这里令人不安的部分是第 0 节中的单元格(那里只有 1 行)没有子视图。但是当我快速上下滚动时,它会得到一个(显然来自第 1 节),然后我会收到“WHAT THE HECK”日志消息......

值得一提的是,使用 for 循环(带有什么鬼消息的循环)确实解决了问题(因为它删除了不需要的子视图),但必须有更好的方法。现在感觉不对。

有任何想法吗?

(请随意将其标记为重复,但我相当肯定这里还有其他事情发生)。

谢谢。

4

3 回答 3

4

所以经过一点挫折,仔细分析后,我发现了为什么细胞会混在一起。

我对单元重用(尤其是标识符)的假设是问题所在。

以前我是这样做的:

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

这很好,但是有一个关键问题。所有单元在技术上都是相同的......在它们都被分配(不是零)之后,系统无法确定要重用哪个单元,无论它是哪个部分。

这意味着任何单元格都可以从队列中被抓取,无论它里面有什么,并卡在任何地方(尽管我检查以确保第 1 部分的东西进入第 1 部分,而第 0 部分的东西(假租客)留在那里) .

解决方案:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Note: the if (cell == nil) thing is no longer required in iOS 6
static NSString *CellIdentifier1 = @"Cell";
static NSString *CellIdentifier2 = @"Cell2";

UITableViewCell *cell;

if (indexPath.section == 0)
{
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier1];
    }
    else
    {
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
    }

}
else
{
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier1];
    }
    else
    {
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
    }
}


if (closestRenter != nil)
{
    NSLog(@"CLOSEST RENTER!");
    [self setupCellsWithClosestRenterCell:cell atIndexPath:indexPath];
}
else
{
    NSLog(@"NO CLOSEST RENTER");
    [self setupCellsWithNoClosestRenterCell:cell atIndexPath:indexPath];
}

return cell;

}

如您所见,第 0 节将获得自己的单元格标识符。第 1 节也是如此。结果是,当一个单元格要出列时,它将检查 indexPath 当前位于哪个节并获取正确的单元格。

呃,这样一个令人沮丧的问题,但现在一切都说得通了 :)

于 2013-05-09T19:26:09.053 回答
1

添加一个 else 解决了我的问题。我在哪里重置了对单元格所做的任何更改。

if (! self.cell) {

self.cell = [[LanguageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

self.cell.accessoryType = UITableViewCellAccessoryNone;
}
else {
self.cell.checkImage.image = NO;

}
于 2014-01-22T04:51:51.443 回答
0

有几种方法可以处理这个单元重用问题(这就是问题所在),而且你现在这样做的方式还可以。问题是,当您向下滚动并再次向上滚动时,为第 0 节返回的单元格可能是以前用于第 1 节的单元格,因此它将包含您放入的任何子视图。

处理这个问题的另一种方法是在情节提要中创建两个不同的原型单元,并为第 0 节返回一个带有简单标签的单元格,并为第 1 节返回另一个在 IB 中添加任何子视图的单元格。这样,您将始终为每个部分获得正确类型的单元格,而无需删除任何子视图——您只需使用正确的数据重新填充单元格。

于 2013-05-07T19:25:11.217 回答