Перезагрузить uitableview с новыми данными, вызвавшими мерцание

Я добавил бесконечную функцию прокрутки и понял, что всякий раз, когда я перезагружаю uitableview, вид мерцает. Я не уверен, как исправить мерцание в этот момент. Пожалуйста, помогите, спасибо!

Я видел очень похожий вопрос, но никакого решения для него. Я попытался опубликовать автора, но он не работает: "удалите представление таблицы из родительского представления, перезагрузите данные, верните представление таблицы в родительский вид" (UITableView reloadData - как для остановки мерцания)

код:       [self.tableView reloadData];

Ответ 1

Как вы уже догадались, мерцание вызвано вызовом [self.tableView reloadData]; быстро и многократно, особенно на устройствах iOS 5.x. Но вы, вероятно, не хотите перезагружать всю таблицу, вы хотите обновить только представление в видимых ячейках таблицы.

Допустим, вы хотите обновить каждую ячейку таблицы, чтобы отразить последние% загрузки по мере загрузки файла. В моем примере вызывается метод [download: totalRead: totalExpected:], который выполняется очень быстро по мере загрузки байтов.

Это то, что НЕ нужно делать... перезагружать таблицу при каждом небольшом обновлении (в этом примере разработчик может использовать методы cellForRowAtIndexPath или willDisplayCell для обновления всех видимых ячеек):

    - (void)downloading:(PPFile *)file totalRead:(long long)read totalExpected:(long long)expected {
        // Bad! Causes flickering when rapidly executed:
        [self.tableView reloadData];
    }

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

    - (void)downloading:(PPFile *)file totalRead:(long long)read totalExpected:(long long)expected {
        NSArray *cells = [self.tableView visibleCells];

        for(MYCellView *cell in cells) {
            if(cell.fileReference == file) {
                // Update your cell view here.
            }
        }
    }

РЕДАКТИРОВАТЬ: Документы рекомендуют то же самое:

При вызове этого метода табличное представление запрашивает у своего источника данных новые ячейки для указанных разделов. Табличное представление оживляет вставку новых ячеек, поскольку оно оживляет старые ячейки. Вызовите этот метод, если вы хотите предупредить пользователя об изменении значений указанных разделов. Если, однако, вы просто хотите изменить значения в ячейках указанных разделов без предупреждения пользователя, вы можете получить эти ячейки и напрямую установить их новые значения.

Ответ 2

Ниже код работал для меня как шарм!

Objective-C

[UIView performWithoutAnimation:^{
   [self.tableview reloadData];
   [self.tableview beginUpdates];
   [self.tableview endUpdates];
}];

Swift 4

UIView.performWithoutAnimation {
    self.tableView.reloadData()
    self.tableView.beginUpdates()
    self.tableView.endUpdates()
}

Ответ 3

    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:index] withRowAnimation:UITableViewRowAnimationNone];

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

вы удаляете строку из таблицы, но не из datasource..so строки удаляются, но ваш источник данных все же указывает, что ни одна строка не удалена. 20 объектов все еще существуют. ваш источник данных будет чем-то вроде

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return MyDataModel.count; // 
}

поэтому вам нужно удалить или добавить новые данные в источник данных также.. что-то вроде этого

   NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
   [MyDataModel removeObjectAtIndex:index.row];
   [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:index] withRowAnimation:UITableViewRowAnimationNone];

Ответ 4

Почему бы вам просто не вызвать метод reloadSections вместо [self.tableView reloadData];

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

Ответ 5

y вы используете deleteRowsAtIndex? Если вы перезагружаете таблицу, вызываются все методы делегата таблицы. Я думаю, что требуется время, чтобы удалить все строки, а затем снова перезагрузить. Просто используйте метод перезагрузки и попробуйте.

Ответ 6

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

Я удалил его и работал у меня.

Ответ 7

На всякий случай, все остальные ответы не решают вашу проблему, я отправляю свое решение.

Если вы используете оцененную высоту estimatedSectionHeaderHeight или estimatedRowHeight или -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath и динамическое число строк для каждого раздела (например, расширяемый двухуровневый tableView)

вы должны прекратить использовать это и реализовать -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath, чтобы вернуть правильную высоту.

Ответ 8

какая работа в моем проекте была:

UIView.PerformWithoutAnimation(() =>
{
tableView.ReloadData();
tableView.LayoutIfNeeded();
});

(это в С# xamarin... но то же самое с быстрой объективностью c)

Ответ 9

Ты добавил это в клетку?

cell.selected = YES;

Если вы сделали и не хотите мерцание экрана, вы должны добавить это:

cell.selectionStyle = UITableViewCellSelectionStyleNone;

Надеюсь, это полезно.

Ответ 10

Для меня это произошло потому, что я явно переключил темы для вызова API Kingfisher.

DispatchQueue.global().async {
    imageView.kf.setImage...
}

Не делай этого. Kingfisher должен установить ваше изображение предварительного просмотра, и если вы переключите его в фоновый поток, у вас будут проблемы с мерцанием при перезагрузке.