代码之家  ›  专栏  ›  技术社区  ›  michaelsnowden

UITableViewController更改一个可重用单元格会影响其他单元格

  •  5
  • michaelsnowden  · 技术社区  · 10 年前

    我有一个非常简单的 UITableViewController 子类,用于在单元格中向用户显示字母表中的字符。当用户按下单元格时,将其附件类型设置为选中标记。

    #import "MTGTableViewController.h"
    
    @interface MTGTableViewController ()
    
    @property (nonatomic, strong) NSArray *data;
    
    @end
    
    @implementation MTGTableViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        _data = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z"];
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        // Return the number of sections.
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return _data.count;
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath];
    
        // Configure the cell...
        cell.textLabel.text = _data[indexPath.row];
    
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    
    @end
    

    表视图工作正常。我在原型单元格的故事板中设置了reuseIdentifier属性,在开始选择单元格之前,这一切看起来都很好。

    问题是: 当我选择任何单元格时,比如“A”单元格,当我向下滚动到其他不可见的单元格时,它们也会被选中。更糟糕的是,当我上下滚动时,有时单元格“A”上的复选标记会被删除,并赋予单元格“B”。

    4 回复  |  直到 10 年前
        1
  •  6
  •   Nicholas Hart    10 年前

    这是因为表视图重用单元格的方式。调用dequeueReusableCellWithIdentifier后,需要确保清除附件项。如:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath];
    
        // Configure the cell...
        cell.textLabel.text = _data[indexPath.row];
        cell.accessoryType = UITableViewCellAccessoryNone;
    
        return cell;
    }
    

    尽管,在你做出这个改变之后,你会有一个不同的问题。该单元格将“忘记”它是因为此代码而被选中的。因此,您需要实际更改accessoryType设置的行,以检查单元格是否被选中。

        2
  •  3
  •   David Cao    10 年前

    不久前我也遇到过这个问题,您需要添加另一个数组来跟踪标记的单元格。只需创建一个标记的NSIndexPath数组。 有点像:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
         UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
         if ([arrayOfMarked containsObject:indexPath]) {
             cell.accessoryType = UITableViewCellAccessoryNone;
         } else {
             cell.accessoryType = UITableViewCellAccessoryCheckmark;
         }
    }
    
        3
  •  1
  •   JHaley2525    7 年前

    对于Swift 3:

    我发现的一个简化版本是使用雨燕 “.indexPathsForSelectedRows” 就在“cellForRowAt”函数中。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
    
        //To keep from reusing checkmark in reusableCell
        if let selectedIndexPaths = tableView.indexPathsForSelectedRows {
            if selectedIndexPaths.contains(indexPath) {
                cell.accessoryType = .checkmark
            } else {
                cell.accessoryType = .none
            }
        }
    
        cell.contactsOutlet.text = namesOrganized[indexPath.section].names[indexPath.row]
        return cell
    }
    

    然后在didSelect和didDeselect中:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
        let cell = tableView.cellForRow(at: indexPath)
        cell?.accessoryType = UITableViewCellAccessoryType.checkmark
    }
    
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    
        let cell = tableView.cellForRow(at: indexPath)
        cell?.accessoryType = UITableViewCellAccessoryType.none
    }
    
        4
  •  0
  •   Led    8 年前

    在didselectRowAtIndex路径上,将索引路径追加到indexpath数组中

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    
    
        if selectedIndexPaths.contains(indexPath) {
    
            let indexOfIndexPath = selectedIndexPaths.indexOf(indexPath)!
            selectedIndexPaths.removeAtIndex(indexOfIndexPath)
        } else {
            selectedIndexPaths += [indexPath]
        }
    
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    
    }
    

    然后在cellForRowAtIndexPath上使用selectedIndexpaths数组检查该单元格是否已选中

     override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let mycell = tableView.dequeueReusableCellWithIdentifier("yourCell", forIndexPath: indexPath) as! YourCustomCell
     .
     .
     .
        if selectedIndexPaths.contains(indexPath){
     // do what you want to do if the cell is selected
    
    
        } else {
    
     // do what you want to do if the cell is not selected
        }