Множественный выбор UITableView
Как я могу добавить UITableView в мое приложение на основе View, где пользователь будет использовать несколько ячеек, и он станет выбранным, точно так же, как и приложение "Новый будильник" Clock Clock с названием "Repeat" (Часы > Сигналы тревоги > + > Repeat), и как я могу получить все выделенные ячейки в массиве?
Ответы
Ответ 1
В вашей реализации -tableView:didSelectRowAtIndexPath:
вы должны установить свойство ячейки таблицы accessoryType
в зависимости от его текущего значения (так что он будет включать и выключать с несколькими кранами). Например:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
Вы можете либо сохранить массив выбранных состояний в дополнение к собственному состоянию типа аксессуаров ячеек, либо выполнить итерацию по ячейкам в представлении табличного представления для каждого одного состояния, чтобы считывать выбранные строки.
Ответ 2
Для множественного выбора добавьте строку ниже в viewDidLoad()
tableView.allowsMultipleSelection = true
Настройте каждый cell
после удаления (или инициализации) его в tableView(_:cellForRowAt:)
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 }
Ответ 3
@BrendanBreg реализация не сработала для меня. @RaphaelOliveira предоставила хорошее решение, но когда вы прокручиваете таблицу вниз, выбираются неправильные строки (потому что UITableView
кэширует ячейки). Итак, я немного изменил решение Рафаэля:
- (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;
}
}
Ответ 4
Просто подскажите в дополнение к большому ответу выше: подражать стилю Apple из приложения часов (если после выбора/снятия строки строки вытереть цвет выбора строки), добавьте это в didSelectRowAtIndexPath
после условные:
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
Из руководства Apple TableMultiSelect.
Ответ 5
self.tableView.allowsMultipleSelection = YES;
Ответ 6
Вот что вам нужно
http://developer.apple.com/library/ios/#samplecode/TableMultiSelect/Introduction/Intro.html#//apple_ref/doc/uid/DTS40011189-Intro-DontLinkElementID_2
Ответ 7
Я видел эту проблему со многими разработчиками. Из-за особенностей вида таблицы повторного использования ячейки он удаляет или случайно обнаруживает чеки. Я создал для этого рабочее решение. Клонировать/скачать код из 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
Ответ 8
Сигналы будильника для повторного просмотра таблицы не являются множественным выбором. Подумайте об этом как об освещении флажков.
Когда ячейка выбрана, цвет шрифта и тип аксессуара изменяются, и выбор исчезает. Когда выбрана ячейка с проверкой, цвет шрифта и тип аксессуара меняются назад, а выбор исчезает.
В вашем делетеледателе didSelectRowAtIndexPath вы должны установить цвет текста и тип аксессуара для выбранной ячейки, а затем отменить выбор ячейки. Вы также должны записать новое состояние в своей модели данных. Это может быть так же просто, как битовая маска, представляющая выбранное состояние, но зависит от того, какие данные вы показываете.
В вашем методе cellForRowAtIndexPath: dataSource установите цвет текста и тип аксессуаров на основе вашей модели данных.
Фактический множественный выбор будет аналогичным. Вы должны следить за тем, какие ячейки выбраны, и установить выбранную ячейку каждого состояния по мере ее создания или показания. Когда в представлении таблицы указано, что ячейка выбрана, переключите состояние выбора в своей модели данных и соответствующим образом настройте выбранное состояние ячейки.
Ответ 9
Вы не можете отменить indexPath, потому что ячейки, которые ссылаются на изменения, как вы scoll. Поместите NSLog в cellForRowAtIndexPath, чтобы это увидеть. Вы можете выполнить check/uncheck в файле willSelectRowAtIndexPath или didSelectRowAtIndexPath. Это касается только начальной проверки или снятия флажка, хотя и будет отображаться как указано после прокрутки, потому что изменяется базовая ячейка для данного индекса.
Итак, решение, которое я нашел, состоит в том, чтобы иметь массив выбранных вещей с чем-то, что является специфичным для данной ячейки, и выполнить начальную проверку.
- (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;
}
Ответ 10
1 - разрешить множественный выбор и переключить выбранное состояние:
tableView.allowsMultipleSelection = true
2 - Собирайте или получите массив всех выбранных индексов, когда вы закончите:
let selected = tableView.indexPathsForSelectedRows
Примечание. Это не зависит от того, какие ячейки в данный момент отображаются на экране.
3 - Измените внешний вид ячейки в зависимости от выбранного состояния: переопределите этот метод в подклассе UITableViewCell. Если у вас нет подкласса, сделайте его.
// In UITableViewCell subclass
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
accessoryType = selected ? .Checkmark : .None
}