iOS:CellForRowAtIndexPath的单元格被搞混了

iOS:CellForRowAtIndexPath的单元格被搞混了,ios,objective-c,uitableview,Ios,Objective C,Uitableview,首先,我要说我看到了这些问题: 第一个和最后一个似乎与我的问题非常相关,但我相当肯定,我有每个部分的逻辑来确定单元格中应该出现什么(数据),但它们仍然混淆 以下是相关代码: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //Note: the if (cell == nil) thing is no longer require

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

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

以下是相关代码:

- (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) CloseStrenger不是零。。。它存在。所以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) 始终有两个部分

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

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

令人不安的是,第0节中的单元(那里只有一行)没有子视图。但当我快速上下滚动时,它会得到一个(显然是从第1节中),然后我会得到“该死的”日志消息

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

有什么想法吗

(请随意将此标记为副本,但我相当肯定这里还发生了其他事情)


谢谢。

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


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

因此,经过一点挫折和仔细分析,我找到了单元格混淆的原因

我关于单元重用(特别是标识符)的假设就是问题所在

以前我是这样做的:

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
这很好,但是有一个关键问题。所有的细胞在技术上都是一样的。。。分配完所有单元后(不是零),无论单元是哪个部分,系统都无法确定要重用哪个单元

这意味着任何一个单元都可能被从队列中抢走,不管它里面有什么,然后卡在任何地方(尽管我检查了一下,确保第一节的东西进入了第一节,而第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当前位于哪个部分,并获取正确的单元格


啊,这是一个令人沮丧的问题,但现在一切都有了意义:)

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

if (! self.cell) {

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

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

}

在故事板中使用原型单元可能会在这方面有所帮助,但是项目没有使用故事板(我在团队中,它们可能是一个问题)。只有Xib文件。@JordanJohns,您还可以在Xib文件中创建自定义单元格。在这种情况下,您需要使用UITableView方法RegisterInB:forCellReuseIdentifier:注册该文件。注册要使用的每个单元格,通常在表数据源的viewDidLoad方法中。做得好!这帮我省去了很多挫折。可爱的法律宝贝耶稣+10000