Ответ 1
Простым способом является что-то вроде этого:
NSIndexPath *ipath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:ipath animated:NO scrollPosition:UITableViewScrollPositionNone];
Я пишу пользовательский jabber-клиент в iphone.
Я использую xmppframework как движок.
И у меня есть UITableViewController с NSMutableArray для отображения списка контактов.
Когда я получаю (или кто-то меняет его содержимое) список (aka список контактов), я хочу изменить элементы UITableView (добавить/удалить/изменить). Поэтому, если пользователь работает с listView в момент обновления списка с помощью
[items addObject:newItem];
[self.tableView reloadData];
пользователь потерял текущий элемент выбора.
Итак, мой вопрос заключается в том, как сохранить (если возможно, я имею в виду, если данный выбранный элемент не удален) текущий элемент select после reloadData?
спасибо.
Простым способом является что-то вроде этого:
NSIndexPath *ipath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:ipath animated:NO scrollPosition:UITableViewScrollPositionNone];
Добавление бит в ответ Марко:
Во-первых, если вы используете множественный выбор, вы можете добавить этот метод к своему ViewController
и называть его всякий раз, когда вам нужно позвонить [tableView reloadData]
:
- (void)reloadTableView
{
NSArray *indexPaths = [self.tableView indexPathsForSelectedRows];
[self.tableView reloadData];
for (NSIndexPath *path in indexPaths) {
[self.tableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Во-вторых, если вы находитесь в UITableViewController
, и вы хотите сохранить выделение после появления таблицыView, там появляется функция в UITableViewController: clearsSelectionOnViewWillAppear
вы можете включить или выключить.
Смотрите здесь: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewController_Class/Reference/Reference.html
Добавление задержки для меня не работало (тестировалось на iOS 8.4 и iOS 9). Что работала, добавляя вызов к -layoutIfNeeded
в выбранной ячейке после вызова -selectRowAtIndexPath:animated:scrollPosition:
.
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[[self.tableView cellForRowAtIndexPath:selectedIndexPath] layoutIfNeeded];
Обходной путь заключается в использовании reloadSections: вместо reloadData. По какой-то причине reloadData удаляет текущий выбор.
В iOS 9.3 и Swift 2.x мне просто нужно было вызвать функцию в главном потоке :)
self.tableView?.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
Swift 4.2 протестирован
Правильный способ обновления выбранных строк после перезагрузки табличного представления:
let selectredRows = tableView.indexPathsForSelectedRows
tableView.reloadData()
DispatchQueue.main.async {
selectredRows?.forEach({ (selectedRow) in
tableView.selectRow(at: selectedRow, animated: false, scrollPosition: .none)
})
}
Это работает для меня:
NSIndexPath *indexPath = [table indexPathForSelectedRow];
[table reloadData];
double delayInSeconds = 0.01;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.table selectRowAtIndexPath:indexPath animated:YES
scrollPosition:UITableViewScrollPositionNone];
});
Трюк заключается в том, чтобы сделать selectRowAtIndexpath запущенным позже. Код выше - это шаблон Xcode, который вы можете выбрать, когда начинаете писать dispatch_after
.
Это решение для случая, если вы хотите сделать обновления таблиц и сохранить выбор:
NSIndexPath* pathToSelect = [self.tableView indexPathForSelectedRow];
if (pathToSelect && newRows) {
int row = pathToSelect.row;
for (NSIndexPath* path in newRows) {
if (path.section == pathToSelect.section && path.row <= pathToSelect.row) {
row++;
}
}
pathToSelect = [NSIndexPath indexPathForRow:row inSection:pathToSelect.section];
}
[self.tableView beginUpdates];
if (reloadRows) [self.tableView reloadRowsAtIndexPaths:reloadRows withRowAnimation:UITableViewRowAnimationFade];
if (newSections) [self.tableView insertSections:newSections withRowAnimation:UITableViewRowAnimationFade];
if (newRows) [self.tableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
if (pathToSelect) {
[self.tableView selectRowAtIndexPath:pathToSelect animated:NO scrollPosition:UITableViewScrollPositionNone];
}
SWIFT 3:
self.collectionView.reloadData()
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
Я решил ее лучше, объявив массив для хранения, скажем, идентификатора или строкового текста выбранной ячейки, и добавив его в функцию didSelectItemAtIndexPath. Таким образом, даже если количество строк изменяется, выбранные не будут. Например:
var selectedItems: [String] = [] // This array type really depends on your preference and what property you're using to store
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
selectedItems.append(cell.textField.text)
}
И на вашей начальной ячейке ForItemAtIndexPath
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath)
if let text = cell.textField.text {
if selectedItems.contains(text) {
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])
}
}
return cell
}
Похоже, что вы не используете "модель" для данных, а просто обновляете "представление" (пользовательский интерфейс) и, вероятно, плохой дизайн.
reloadData должно привести к обновлению представления с данными из модели, которые должны содержать самые последние данные, которые будут отображаться.
искать ресурсы в шаблоне контроллера модели модели