Подтвердить что ты не робот

Сохранить выбранную строку в UITableView после reloadData

Я пишу пользовательский jabber-клиент в iphone.

Я использую xmppframework как движок.

И у меня есть UITableViewController с NSMutableArray для отображения списка контактов.

Когда я получаю (или кто-то меняет его содержимое) список (aka список контактов), я хочу изменить элементы UITableView (добавить/удалить/изменить). Поэтому, если пользователь работает с listView в момент обновления списка с помощью

[items addObject:newItem];
[self.tableView reloadData];

пользователь потерял текущий элемент выбора.

Итак, мой вопрос заключается в том, как сохранить (если возможно, я имею в виду, если данный выбранный элемент не удален) текущий элемент select после reloadData?

спасибо.

4b9b3361

Ответ 1

Простым способом является что-то вроде этого:

NSIndexPath *ipath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:ipath animated:NO scrollPosition:UITableViewScrollPositionNone];

Ответ 2

Добавление бит в ответ Марко:

Во-первых, если вы используете множественный выбор, вы можете добавить этот метод к своему 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

Ответ 3

Добавление задержки для меня не работало (тестировалось на 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];

Ответ 4

Обходной путь заключается в использовании reloadSections: вместо reloadData. По какой-то причине reloadData удаляет текущий выбор.

Ответ 5

В iOS 9.3 и Swift 2.x мне просто нужно было вызвать функцию в главном потоке :)

self.tableView?.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)

Ответ 6

Swift 4.2 протестирован

Правильный способ обновления выбранных строк после перезагрузки табличного представления:

let selectredRows = tableView.indexPathsForSelectedRows

tableView.reloadData()

DispatchQueue.main.async {
    selectredRows?.forEach({ (selectedRow) in
        tableView.selectRow(at: selectedRow, animated: false, scrollPosition: .none)
    })
}

Ответ 7

Это работает для меня:

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.

Ответ 8

Это решение для случая, если вы хотите сделать обновления таблиц и сохранить выбор:

    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];
    }

Ответ 9

SWIFT 3:

self.collectionView.reloadData()
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])

Ответ 10

Я решил ее лучше, объявив массив для хранения, скажем, идентификатора или строкового текста выбранной ячейки, и добавив его в функцию 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
}

Ответ 11

Похоже, что вы не используете "модель" для данных, а просто обновляете "представление" (пользовательский интерфейс) и, вероятно, плохой дизайн.

reloadData должно привести к обновлению представления с данными из модели, которые должны содержать самые последние данные, которые будут отображаться.

искать ресурсы в шаблоне контроллера модели модели