SetNeedsDisplay не всегда вызывает drawRect
У меня есть пользовательский вид в пользовательской ячейке таблицы. Каждый раз, когда изменяется определенное свойство в пользовательском представлении, я вызываю [self setNeedsDisplay]
, который перерисовывает представление в - (void)drawRect:(CGRect)rect
. Это свойство задается в делегате таблицы tableView:cellForRowAtIndexPath:
. Но когда представление таблицы больше, чем экран, и ячейки необходимо повторно использовать, drawRect
не вызывается каждый раз, когда setNeedsDisplay
есть. Особенно, когда я быстро рисую стол. Медленная прокрутка отлично работает. Это приводит к тому, что информация в первой и последней ячейках часто неверна.
В журнале я вижу, что обычно для каждого вызова setNeedsDisplay
есть вызов drawRect
, но когда я быстро прокручиваю представление таблицы, появляется больше вызовов setNeedsDisplay
, чем drawRect
. Разумеется, здесь должно быть соотношение "один-к-одному".
Я использую тот же пользовательский вид в обычном UIView, и он перерисовывается идеально каждый раз, когда я вызываю setNeedsDisplay
. Проблема кажется изолированной от представлений таблиц и повторного использования ячеек.
Кто-нибудь знает, что здесь происходит?
Есть ли другой способ заставить пользовательский вид перерисовать себя?
Ответы
Ответ 1
Я думаю, что я боролся с этой проблемой почти неделю, прежде чем я нашел проблему. Вот оно, и я не хочу тебя забыть:
Указатель этого пользовательского представления был определен в файле .m вместо файла .h, что делает его переменной класса вместо переменной экземпляра.
И да, я очень, очень смущен.
Ответ 2
setNeedsDisplay
будет вызывать только drawRect:
, если вид виден, в противном случае он недействителен на уровне представления, и drawRect:
будет вызываться, когда он станет видимым.
При прокрутке просмотра таблицы представление таблицы запрашивает ячейки в надежде добавить их в представление. Если прокрутка достаточно быстро, некоторые ячейки займут слишком много времени, чтобы подготовиться, и к тому времени, когда они будут готовы, местоположение, в котором они должны быть расположены, является вне экрана. В этих случаях представление таблицы отбрасывает их вместо добавления их в представление прокрутки (и, следовательно, drawRect:
не будет вызываться)
Ответ 3
Вы должны вызвать [_table_ reloadData]
, чтобы перерисовать таблицу. Не [_table_cell_ setNeedsDsiplay]
Ответ 4
Похоже, есть два обстоятельства, при которых обновляется представление: если внутреннее значение изменяется (и вы вызываете [self setNeedsDisplay]
для принудительного обновления), а также, если tableview запрашивает, чтобы ячейка была нарисована (или повторно использована), Вы явно не перерисовываете этот пользовательский вид в этой ситуации.
Согласно документам:
Делите делегат таблицы в tableView: cellForRowAtIndexPath: всегда должен reset весь контент при повторном использовании ячейки.
Если tableview - это утилизация ячеек, он передаст ячейку со старыми значениями, все еще находящимися на месте. Это зависит от вас, чтобы убедиться, что контент обновлен. В зависимости от того, как вы настроили свою настраиваемую ячейку таблицы, вам, возможно, придется сделать больше, чтобы убедиться, что представление устарело, но самое простое в обработчике ячейки таблицы, чтобы заставить вызов [myCustomView setNeedsDisplay]
.