UITableView重用标识符

时间:2015-05-03 22:20:15

标签: ios uitableview

直到今天我还以为我理解了UITableView,但是由于在滚动问题时我一直在努力解决滚动和内容不匹配问题,因此感觉已经发生了变化。

我有一个小的表视图,可能有20-30行,具体取决于用户内容。当我滚动(比通常快一点)时,内容混淆了。一些附件视图互换,背景颜色被交换或覆盖;有时甚至文本都会改变。

我对某些单元格使用重用标识符,但我不确定它是否正常运行。

的问题:

  1. 显然,单个重用标识符不会将其删除 - 作为第一个和最后一个单元格交换值。

  2. 对于第一个,最后一个和剩余的单元格(包含设置)有3个重用标识符,附件视图在包含设置的某些单元格之间互换,即在某些情况下我使用开关控件,在其他情况下我使用附件细节按钮,有亵渎。

  3. 即使对不同类型的内容使用5个重用标识符,附件视图也会与其他单元格的背景颜色不匹配。

  4. 我一直在写表格视图,我以前从未遇到过这些问题。所以我有一个简单的问题 - 你什么时候创建重用标识符?

    • 仅当文字/图片内容不同时?
    • 当配件视图相同时?即,对于不同的附件视图,创建不同的重用标识符

    我完全迷失了,所以如果你能真正做出解释,我会非常感激。

    编辑:过去5个小时我一直在研究这个问题,并且在StackOverflow上经历了大量的文献和开放/封闭问题。我理解可重复使用的细胞是什么。提供的主题不回答非常具体的问题。

    以下是一些代码:

    // previously had 3 different types of cells; currently doing with one only
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (!cell)
        {
            cell = [[ESBasicTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }
    
        [self configureCell:cell atIndexPath:indexPath];
        return cell;
    }
    
    - (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *FirstCellId = @"First";
        static NSString *SecondCellId = @"Second";
        static NSString *ThirdCellId = @"Third";
        static NSString *ForthCellId = @"Forth";
        static NSString *FifthCellId = @"Fifth";
        static NSString *SixthCellId = @"Sixth";
    
        NSString *cellIdentifier = nil;
        if (indexPath.section == kSectionFirst && indexPath.row == kRowFirst)
        {
            cellIdentifier = FirstCellId;
        }
        else if (indexPath.section == kSectionFirst && indexPath.row == kRowSecond)
        {
            cellIdentifier = SecondCellId;
        }
        else if (indexPath.section == kSectionSecond)
        {
            cellIdentifier = ThirdCellId;
        }
        else if (indexPath.section == kSectionThird)
        {
            cellIdentifier = ForthCellId;
        }
        else if (indexPath.section == kSectionSettings)
        {
            cellIdentifier = FifthCellId;
        }
        else if (indexPath.section == kSEctionFifth)
        {
            cellIdentifier = SixthCellId;
        }
    
        return cellIdentifier;
    }
    

    configureCell:atIndexPath方法导致其他配置调用;其中一个是设置配置:

    - (void)configureCellForSettings:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
    {
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
        switch (indexPath.row)
        {
            case kRowNotificationSetting:
            {
                cell.textLabel.text = @"Notifications";
                cell.accessoryType = UITableViewCellAccessoryDetailButton;
                cell.imageView.image = [[UIImage imageNamed:@"cell_notification_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
                break;
            }
            case kRowSomeOtherSetting:
            {
                cell.textLabel.text = @"Auto";
                cell.imageView.image = [[UIImage imageNamed:@"cell_auto_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    
                UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
                [switchView addTarget:self action:@selector(changed:) forControlEvents:UIControlEventValueChanged];
                [switchView setOn:...];
    
                cell.accessoryView = switchView;
                break;
            }
            default:
                break;
        }
    }
    

    一些有意义的文字被删除了(不幸的是)。第四部分是设置,但这只是一个例子。

    修改:此处为configureCell:atIndexPath:

    - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
    {
        if (indexPath.section == kSectionFirst)
        {
            // ...
            [self configureFirstCell:cell atIndexPath:indexPath];
        }
        else if (indexPath.section == kSectionSecond)
        {
            // ...
            [self configureSecondCell:cell atIndexPath:indexPath];
        }
        else if (indexPath.section == kSectionThird)
        {
            // add ...
            [self configureThirdCell:cell atIndexPath:indexPath];
        }
        else if (indexPath.section == kSectionSettings)
        {
            // settings
            [self configureCellForSettings:cell atIndexPath:indexPath];
        }
        else if (indexPath.section == kSectionFifth)
        {
            // delete button
            [self configureFifthCell:cell atIndexPath:indexPath];
        }
    }
    

    请注意 - 我必须重命名很多代码才能在StackOverflow上使用它。

1 个答案:

答案 0 :(得分:2)

我只是将其标记为副本,因为当您致电dequeueReusableCellWithIdentifier:

时,听起来您正在努力解决实际发生的事情的概念

每当您致电dequeueReusableCellWithIdentifier:以获取单元格时,请尝试概念化您正在返回之前生成的单元格之一,并将内容添加到具有相同标识符的 (事实上,这正是你正在做的事情)。这样返回的单元格可能已经有附件视图/图像集等,您可能需要根据用例取消设置/删除它们。

如果您有多个类型的单元格(布局/内容显着不同),那么您可能需要考虑使用多个重用标识符 - 每种类型的单元格的重用标识符,这样您就可以每次重复使用单元格时,都可以轻松地重复使用单元格,而不是重置所有附件视图/图像/等。