#iphone #objective-c #ios #uitableview
#iPhone #objective-c #iOS #uitableview
Вопрос:
У меня есть разделенный TableView, в котором я хочу, чтобы мой пользователь выбрал один элемент из таблицы. Когда пользователь выбирает элемент, рядом с элементом должен появиться флажок (с помощью UITableViewCellAccessoryCheckmark
). Если они сделали предыдущий выбор, проверка должна быть удалена из ранее выбранной строки. Вот код, который я использую:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
if (newRow != oldRow || newRow == 0)
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
[lastIndexPath release];
lastIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
lastIndexPath
объявляется конфиденциально в .h
файле.
Этот код отлично работает для небольшого списка, который не разделен на разделы. Но в большой таблице, которая разделена, он ставит случайные флажки в строках в других разделах. Это почти так, как если бы cellForRowAtIndexPath
игнорировал раздел в indexPath.
Код также вылетает, если я выбираю строку, которая больше, чем количество строк в наименьшем разделе.
Вот код для cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *itemSection = [items objectForKey:key];
static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SectionsTableIdentifier] autorelease];
}
NSArray *rowLabel = [itemSection objectAtIndex:row];
cell.textLabel.text = [rowLabel objectAtIndex:1];
NSString *detText = [rowLabel objectAtIndex:0];
detText = [detText stringByAppendingString:@" $"];
detText = [detText stringByAppendingString:[rowLabel objectAtIndex:2]];
cell.detailTextLabel.text = detText;
return cell;
}
Комментарии:
1. необходимо просмотреть ваш код для
cellForRowAtIndexPath:
. Я предполагаю, что вы удаляете ячейки из очереди и используете идентификатор повторного использования (реализация по умолчаниюcellForRowAtIndexPath:
). Если это так, то ваш код для создания ячеек будет повторно использовать ячейку, отмеченную флажком, в качестве шаблона для создания новой ячейки. Чтобы решить эту проблему, вы можете сделать несколько вещей: «каждый раз создавать новую ячейку вcellForRowAtIndexPath:
» или «сохранять ссылку на каждую ячейку и обходить вызовыcellForRowAtIndexPath:
»2. Да — я понимаю, что вы говорите, и это могло бы решить первую проблему случайных флажков, но я не думаю, что это решило бы вторую проблему сбоя, если я выберу строку, превышающую количество строк в наименьшем разделе. Вот код cellForRowAtIndexPath:
3. вы не сможете опубликовать этот код в комментарии. Добавьте это в свой исходный пост
Ответ №1:
Одна из проблем, с которой вы сталкиваетесь, заключается в том, как вы сохраняете indexPath в lastIndexPath . Вам необходимо сохранить indexPath, который вы сохраняете в lastIndexPath. indexPath, переданный в этот метод, автоматически освобождается, поэтому, скорее всего, он будет удален из-под вас, если вы его не сохраните. Это может быть причиной вашего сбоя.
Ответ №2:
Вероятно, это именно то, что вы ищете. Я разработал это для одного из своих приложений. Наслаждайтесь! (если это так, пожалуйста, отметьте как ответивший) Также обратите внимание, что я использую ARC, поэтому не сохраняю и не освобождаю.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
1. First we get the indexPath from the prior priorSelectedRowInteger and priorSelectedSectionInteger ivars. Note: we could use a single indexPath ivar, but we separate them into row and section here for clarity.
2. Then we reset the selectedRowInteger ivar to the currently selected row. This must be done before any rows are reloaded.
3. Then we reload only the two rows at the concerned index paths, as we have captured the indexPath of the prior selected row and the method gives us the new one. We could just simply reload the table here with [self.tableView reloadData], but it would not be animated and not as smooth.
*/
NSIndexPath *priorSelectedIndexPath = [NSIndexPath indexPathForRow:priorSelectedRowInteger inSection: priorSelectedSectionInteger];
// Now that we have the priorSelectedIndexPath, we save the new one for the next round.
self.priorSelectedRowInteger = indexPath.row;
self.priorSelectedSectionInteger = indexPath.section;
// For a changing tableView, check to make sure the priorIndexPath is still valid before trying to reload the prior row.
// NSLog(@"priorSelectedIndexPath %@", priorSelectedIndexPath);
if ((tableView.numberOfSections >= priorSelectedIndexPath.section 1) amp;amp; ([tableView numberOfRowsInSection:priorSelectedIndexPath.section] >= priorSelectedIndexPath.row 1)) {
NSArray *thePriorIndexPathArray = [NSArray arrayWithObject:priorSelectedIndexPath];
[self.tableView reloadRowsAtIndexPaths:thePriorIndexPathArray withRowAnimation:UITableViewRowAnimationFade];
}
// Reload only the selected indexPath - necessary to update the text colors etc.
NSArray *theIndexPathArray = [NSArray arrayWithObject:indexPath];
[self.tableView reloadRowsAtIndexPaths:theIndexPathArray withRowAnimation:UITableViewRowAnimationFade];
}