Table View + Fetch Request (Fatal Error: Index Out of Range)

swift
ios

#1

Ситуация:

  • Есть ViewController на котором расположено два элемента - UIPickerView и UITableView
  • При выборе нового значения в UIPickerView у нас сразу происходит запрос на сервер, откуда мы получаем данные
  • После получения данных делаем обновление таблицы с помощью tableView.reloadData()

В чем проблема: Если быстро переключать значения в PickerView, то рано или поздно приложение падает с ошибкой Index out of Range, и ошибка эта появляется в методе cellForRowAtIndexPath

Мне удалось обойти эту ошибку только путем если я делаю UIPickerView недоступным для взаимодействия (isUserIntercationEnabled = false) до того времени, пока мы не получили ответ от сервера.

Я подозреваю что проблема заключается в следующем:

  • Если мы быстро переключаемся между элементами PickerView, то каждое переключение подразумевает запрос данных с сервера (в каком то случае требуется больше времени на их загрузку, в каком то случае требуется меньше времени на их загрузку).
    Соответственно если я переключаюсь на новое значение, в нем начинается загрузка данных и я не дожидаюсь этой загрузки и перевожу PickerView на следующее значение (начинается новая загрузка данных), далее происходит какой то факап в модели на основании которой строится таблица и я получаю собственно ошибку.

Первое что я попробовал сделать, это вызов метода cancel у свойства task своего нетворкменеджера, при переключении на новое значение PickerView, но не помогло

Что посоветуете делать в данной ситуации ?


#2

Как вы уже сами и написали, отмена текущего запроса при переключении в UIPickerView.
А почему не сработало, это вам нужно выяснить.
На практике это делается именно так.


#3

Я бы UI переделал: так Пикер действительно можно крутить быстро, то загрузка никогда не успеет, а фризить интерфейс - это так себе практика. Лучше Пикер заменить отдельным контроллером с таблицей. Можно его выводить popover’ом, если вы не хотите покидать данный контроллер. Жмёте на “нужную кнопку” - вылазит popover с табличкой выбора (обычный тейбл). Юзер жмёт на нужный пункт. Начинается загрузка данных из сети, вы отображаете любой элемент ожидания (пока идёт загрузка). Загрузка закончилась - вы обновляете основной тейбл. Ничего не падает и всё взаимодействие понятно для юзера.


#4

Ребят всем спасибо за помощь

Решил следующим образом:

  • В методе didSelectRow пикерьвю, сделал отмену таска с помощью метода .cancel() прежде чем делать новый реквест

Была ошибка в коде ))