【问题标题】:UITableViewController changing one reusable cell affects other cellsUITableViewController 更改一个可重用单元格会影响其他单元格
【发布时间】:2014-09-06 04:50: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

表格视图工作正常。我在原型单元格的情节提要中设置了我的重用标识符属性,在我开始选择单元格之前,一切看起来都很好。

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

【问题讨论】:

    标签: ios uitableview didselectrowatindexpath reuseidentifier


    【解决方案1】:

    这是因为表格视图重用单元格的方式。您需要确保在调用 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】:

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

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

      【讨论】:

      • 该死,这太糟糕了。但这就是我最终要做的。
      • @michaelsnowden 这不是最好的方法。我问了一个类似的问题,结果你需要为你的单元格提供一个“默认”状态,因为它们正在被重用。 (下面的@Nicolas Hart 实际上是在暗示)这是我的问题的链接; stackoverflow.com/questions/39198461/…
      【解决方案3】:

      对于 Swift 3:

      我发现的一个简化版本是在“cellForRowAt”函数中使用 swifts ".indexPathsForSelectedRows"

      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】:

        在 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
            }
        

        【讨论】:

          猜你喜欢
          • 2016-06-17
          • 1970-01-01
          • 2023-03-31
          • 2019-04-11
          • 1970-01-01
          • 1970-01-01
          • 2010-09-17
          • 2017-06-28
          • 2013-06-04
          相关资源
          最近更新 更多