Реализация кнопок Prev./Next в UITableView, чтобы сделать первого респондента UITextField в невидимой ячейке

в моем приложении у меня есть UITabeView с UITextField внутри каждой ячейки. Однако у меня возникли проблемы с реализацией кнопок «предыдущий / следующий», чтобы текстовое поле внутри предыдущего / следующего UITableViewCell было первым респондентом.

Я разделил класс UITableViewCell на подклассы, чтобы он вызывал определенный метод delegate при нажатии кнопок prev./next и передавал саму ячейку в качестве параметра этого метода (чтобы я мог получить путь к ее индексу для вычисления, который путь индекса ячейки, текстовое поле которой нужно сделать первым респондентом)

В реализации метода делегата I:

  • получить индексный путь ячейки, кнопка которой была нажата
  • добавить или вычесть 1 из пути индекса этой ячейки (в зависимости от того, какая кнопка была нажата)
  • получить ячейку, текстовое поле которой нужно сделать первым респондентом, используя метод -cellForRowAtIndexPath: в представлении таблицы
  • сделать текстовое поле первым респондентом

Проблема в том, что метод -cellForRowAtIndexPath: возвращает ячейку, только если она видна. Поэтому, когда ячейка не видна, она вернет nil, и вышеуказанный алгоритм не будет работать, а когда ячейка отображается на экране, он будет работать правильно.

Вот мой код для пред. при условии, что MUInfoMateriaTableViewCell является моим подклассом UITableViewCell и имеет свойство textField, которое возвращает его текстовое поле:

- (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];

    MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
    [newCell.textField becomeFirstResponder];
}

Есть ли способ «получить» невидимую ячейку, чтобы я мог сделать ее текстовое поле первым респондентом? Или вы можете предложить мне другой алгоритм для решения этой проблемы?


person BigLex    schedule 09.04.2013    source источник


Ответы (3)


Вы можете исправить это с помощью многоэтапного процесса:

  • отслеживать ячейку, содержащую желаемое текстовое поле, чтобы сделать первый ответ
  • вычислить NSIndexPath отображаемой ячейки и вызвать [self.tableView scrollToRowAtIndexPath:atScrollPosition:animated:], чтобы отобразить ее
  • реализовать tableView:willDisplayCell:forRowAtIndexPath: для вызова becomeFirstResponder в желаемой ячейке, когда она становится видимой и соответствует желаемой ячейке или пути индекса

Последний шаг важен, потому что вызов becomeFirstResponder ничего не делает, если получатель не является подпредставлением какого-либо окна.

person jszumski    schedule 16.04.2013
comment
Как вы предлагаете отслеживать ячейку, текстовое поле которой должно стать первым респондентом? Должен ли я иметь ivar, названный чем-то вроде activeCellIndexPath, и проверить, совпадает ли индексный путь активной ячейки с индексным путем ячейки, переданной в качестве параметра в tableView:willDisplayCell:forRowAtIndexPath:, или есть лучший / более эффективный подход? - person BigLex; 16.04.2013
comment
Я бы реализовал именно так, как вы только что описали. Обязательно обработайте случай, когда вы не хотите делать какую-либо ячейку отвечающей и nil из activeCellIndexPath. - person jszumski; 16.04.2013

Сделайте ячейку видимой, прокручивая табличное представление с помощью scrollToRowAtIndexPath:atScrollPosition:animated:.

Например

- (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];

    [self.tableView scrollToRowAtIndexPath:previousIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

    MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
    [newCell.textField becomeFirstResponder];
}
person Gabriele Petronella    schedule 16.04.2013

Проблема в том, что метод -cellForRowAtIndexPath: возвращает ячейку, только если она видна.

Это потому, что ячейка не существует, когда ее строка не отображается. UITableView сохраняет только те ячейки, которые необходимы для рисования таблицы. Вот почему вы получаете много -tableView:cellForRowAtIndexPath: сообщений при прокрутке таблицы - таблица просит свой источник данных предоставить ячейки, которых у нее нет.

Если вы хотите использовать свой текущий подход, вам нужно прокрутить таблицу, чтобы строка, которую предстоит редактировать, стала видимой, как показано в ответе Габриэле Петронеллы.

person Caleb    schedule 16.04.2013
comment
Это просто неправильно. Посмотрите на типичную реализацию tableView:cellForRowAtIndexPath:, и вы увидите, что происходит. Он всегда возвращает ячейку, но может потребоваться создать новую ячейку для этого пути индекса, если она в настоящее время не видна. Или он может все еще иметь его в кеше ячеек, и в этом случае он будет исключен из очереди и вернет уже существующую ячейку. - person Logachu; 26.07.2013
comment
@Logachu Мой ответ правильный в контексте исходного вопроса, но неправильное редактирование изменило -cellForRowAtIndexPath: (метод UITableView) на -tableView:cellForRowAtIndexPath: (метод UITableViewDataSource), что меняет вопрос. Должно быть, это произошло примерно в то же время, когда я отвечал, потому что я скопировал неправильный текст в цитату в своем ответе. Я исправил цитату и вопрос, и если вы прочитаете мой ответ, имея в виду UITableView (и, возможно, проверьте документы) Надеюсь, вы согласитесь, что это правильно. - person Caleb; 26.07.2013