UITableView: Самая распространенная ошибка

U

UITableView является одним из наиболее важных элементов пользовательского интерфейса для iOS приложений. Тем не менее, существует одна самая распространенная ошибка в использовании UITableView, которая сведет вас с ума.

UITableView: Пример

Взгляните на этот код:

Здесь мы попеременно показываем изображение и текст. Результат выглядит так:

UITableView

Кажется, что вроде все в порядке.

UITableView: Проблема

Тем не менее, если мы проскроллим вниз, то увидим что что то пошло не так:

UITableView

И если проскроллим вверх, проблема повторится. Так что же здесь происходит? Ответ на этот вопрос относительно прост. Мы переиспользуем ячейки при помощи метода dequeueReusableCellWithIdentifier. Давайте взглянем на изображение, что бы понять, что произошло:

UITableView

Помимо этого, скорее всего переиспользовалось куда больше ячеек, но мы этого не видим так как у нас лишь одно изображение. Так что такое переиспользование? Дело в том, что UITableView не хранит в памяти ВСЕ ячейки, которые в нем присутствует. Он хранит их столько, сколько помещается на экране. Те ячейки которые выходят за его пределы ПЕРЕИСПОЛЬЗУЮТСЯ для тех, которые появляются. Вы можете заметить, что поведение программы не очень предсказуемо, хотя иногда кажется что все работает нормально. Но каждый раз при скролле результат будет отличаться. Часто эта ошибка остается незамеченной, так как ее трудно воспроизвести, однако ее допускают даже опытные iOS разработчики.

В данном примере мы чередуем изображение и текст: каждую вторую ячейку заполняем фото, а каждую первую — текстом. Проблема в том, что при скролле часть наших ячеек переиспользуется. Так посмотрите на ячейку 16 (с пометкой «ячейка 5 переиспользовалась») — по нашему коду при выводе на экран ячейки 16 сработала проверка: 16 % 2 = 0, а значит, должно отобразиться изображение. Вот только данные на переиспользуемых ячейках никуда не пропадают! А это значит, что на нашей ячейке остался текст, принадлежащий 5й ячейке. Вы почти никогда не заметите это, имея только один тип ячеек в таблице, поскольку данные при переиспользовании будут заменяться. Однако для разных ячеек в одной таблице это станет проблемой.

UITableView: Решение

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

Если изображение или текст не должны отображаться, мы приравниваем их nil. Теперь наша UITableView работает адекватно.

Если не уделять своему коду должного внимания, впоследствии могут всплыть самые не очевидные ошибки. Но если вы будете следовать правилу — создавать свойства и очищать их вовремя, все будет работать как часы.

Поддержите ресурс blog.justDev:

Сведения об авторе

Игорь Малеваный

1 комментарий

  • Для очистки переиспользуемых ячеек существует метод prepareForReuse, который нужно переопределить в классе ячейки. Имхо, это лучше, чем обнулять кучу полей, тем более, что список полей может измениться, а обнулить новое поле во всех таблицах, где оно используется, вы, скорее всего, забудете.

Instagram

Поддержите ресурс blog.justDev:

Свежие записи

Рубрики