UITableView多选

如何将UITableView添加到我的基于视图的应用程序中,用户将点击多个单元格,并将其选中,就像时钟应用程序的“新警报”设置“重复”(时钟>警报> +>重复),以及如何获得数组中的所有选定的单元格?

在你的-tableView:didSelectRowAtIndexPath:实现中,你可以根据当前的值来设置表格视图单元的accessoryType属性(所以它可以通过多次敲击来打开和closures)。 例如:

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

除了单元格自己的附件types状态之外,您还可以维护一个选定状态的数组,或者遍历表视图中的单元格以查询每个状态,以便读出所选的行。

对于多选,请在viewDidLoad()添加以下行

 tableView.allowsMultipleSelection = true 

tableView(_:cellForRowAt:)取出(或初始化)它之后configuration每个cell

 let selectedIndexPaths = tableView.indexPathsForSelectedRows let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath) cell.accessoryType = rowIsSelected ? .checkmark : .none // cell.accessoryView.hidden = !rowIsSelected // if using a custom image 

选中/取消选中时更新每个单元格

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let cell = tableView.cellForRow(at: indexPath)! cell.accessoryType = .checkmark // cell.accessoryView.hidden = false // if using a custom image } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { let cell = tableView.cellForRow(at: indexPath)! cell.accessoryType = .none // cell.accessoryView.hidden = true // if using a custom image } 

完成后,获取所有选定行的数组

 let selectedRows = tableView.indexPathsForSelectedRows 

并获取选定的数据,其中dataArray映射到只有1节的表视图的行

 let selectedData = selectedRows?.map { dataArray[$0.row].ID } 

@BrendanBreg 实现没有为我工作。 @RaphaelOliveira提供了很好的解决scheme ,但是当你滚动你的表时 – 错误的行被选中(因为UITableViewcaching它的单元格)。 所以,我稍微修改了Raphael的解决scheme:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryNone; } /*Here is modified part*/ - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { /* ... Your implementation stays here we're just adding few lines to make sure that only correct rows will be selected */ if([[tableView indexPathsForSelectedRows] containsObject:indexPath]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } } 
 self.tableView.allowsMultipleSelection = YES; 

除了上面的很好的答案之外,还有一个快速的提示:为了模拟时钟应用程序中的Apple风格(在检查/取消选中行之后使行select颜色淡出),在条件之后将其添加到didSelectRowAtIndexPath

 [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 

从Apple的TableMultiSelect指南。

我已经看到了这么多开发者的这个问题。 由于重复使用单元格的表格视图的性质,它删除或随意的检查。 我已经为此创build了一个工作解决scheme。 从DevelopmentSupportWorkspace克隆/下载代码并从那里执行UITableViewTest项目。

这里是代码总结:

 @interface CheckBoxTestTableViewController () @property (nonatomic, strong) NSArray *dataArray; @property (nonatomic, strong) NSMutableDictionary *selectedIndexDictionary; @end @implementation CheckBoxTestTableViewController - (void)viewDidLoad { [super viewDidLoad]; // Uncomment the following line to preserve selection between presentations. // self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; // _dataArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ImageList" ofType:@"plist"]]; _selectedIndexDictionary = [NSMutableDictionary dictionary]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"checkMarkCell" forIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryNone; // Configure the cell... cell.textLabel.text = _dataArray[indexPath.row][@"text"]; if (_selectedIndexDictionary[indexPath] != nil) cell.accessoryType = UITableViewCellAccessoryCheckmark; return cell; } - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath { if (_selectedIndexDictionary[indexPath] == nil) { [_selectedIndexDictionary setObject:_dataArray[indexPath.row] forKey:indexPath]; [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark]; }else{ [_selectedIndexDictionary removeObjectForKey:indexPath]; [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryNone]; } // [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } @end 

时钟报警重复表视图不是多重select。 把它想象成点亮的checkbox。

select单元格时,字体颜色和附件types会更改,select将会淡出。 当选中一个选中的单元格时,字体颜色和附件types会改回,select将淡出。

在didSelectRowAtIndexPath委托方法中,您可以设置所选单元格的文本颜色和附件types,然后取消select该单元格。 您还将在数据模型中logging新的状态。 这可能与表示所选状态的位掩码一样简单,但取决于您显示的数据。

在您的cellForRowAtIndexPath:dataSource方法中,根据您的数据模型设置文本颜色和附件types。

实际的多重select是相似的。 您必须跟踪select哪个单元格,并在创build或显示每个状态时设置所选单元格。 当表格视图报告选中单元格时,切换数据模型中的select状态并相应地设置单元格的选定状态。

您不能键入indexPath,因为引用的单元格随着您的增长而改变。 把一个NSLog的cellForRowAtIndexPath看到。 您可以在willSelectRowAtIndexPath或didSelectRowAtIndexPath中进行选中/取消选中。 这只包括初始检查或取消选中,并且一旦你滚动,因为给定indexPath的底层单元格改变,也会显示为选中状态。

所以我find的解决scheme是有一些选定的东西,特定于特定的细胞arrays,并做初步检查。

 - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath]; if (![selectedIndexes containsObject:cell.textLabel.text]){ [selectedIndexes addObject:cell.textLabel.text]; cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { [selectedIndexes removeObject:cell.textLabel.text]; cell.accessoryType = UITableViewCellAccessoryNone; } return indexPath; } 

您还必须在cellForRowAtIndexPath中有逻辑,以确保正确的东西被检查或没有视图滚动:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ... cell.accessoryType = UITableViewCellAccessoryNone; if ([selectedIndexes containsObject:cell.textLabel.text]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; [cell setSelected:YES animated:YES]; } return cell; } 

1 – 允许多选和切换选中状态:

 tableView.allowsMultipleSelection = true 

2 – 完成后收集或获取所有选定索引的数组:

 let selected = tableView.indexPathsForSelectedRows 

注意:这与当前显示在屏幕上的单元无关。

3 – 根据所选状态更改单元格的外观:在您的UITableViewCell子类中重写此方法。 如果你没有一个子类,就创build一个子类。

 // In UITableViewCell subclass override func setSelected(selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) accessoryType = selected ? .Checkmark : .None }