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].