Установка изображения в пользовательской uitableviewcell вызывает задержку

#ios #uitableview #uiimageview #uiimage

#iOS #uitableview #uiimageview #uiimage

Вопрос:

У меня есть uitableview, где я использую пользовательскую ячейку. Однако при прокрутке табличного представления возникает серьезная задержка. Это происходит, когда я устанавливаю свойство изображения UIImaveView с изображением. Я получаю доступ к изображению из каталога. Но поскольку ввод-вывод файлов происходит медленно, я использую dispatch_async для загрузки изображения в объект UIImage в отдельном потоке.

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

Я не уверен, что вызывает задержку. Сначала я подумал, что это связано с тем, что изображение слишком большое, поэтому я попытался уменьшить его. Все еще лагает. Опять же, если я не установлю изображение в пользовательской ячейке, задержки не будет. Но когда я его устанавливаю, возникает задержка. Я не уверен, как это исправить.

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    DHTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kReuseIdentifierGoalCell forIndexPath:indexPath];
    [self configureCell:cell forIndexPath:indexPath isForOffscreenUse:NO];

    return cell;
 }


- (void)configureCell:(DHTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath isForOffscreenUse:(BOOL)offscreenUse {
    if (cell == nil) {
        return;
    }

    [cell setDelegate:self];

    PATH_TO_FILE = SQLITE_QUERY_TO_GET_PATH; //some pseudo codes

    __weak typeof(sSelf)wSelf = sSelf;
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         __strong typeof(wSelf)sSelf = wSelf;
         UIImage *unscaled_image = [UIImage imageWithContentsOfFile:PATH_TO_FILE];
         UIImage *image = [unscaled_image imageScaledToFitInSize:kCellUIImageSize];
         __weak typeof(sSelf)wSelf = sSelf;
         dispatch_async(dispatch_get_main_queue(), ^{
             __strong typeof(wSelf)sSelf = wSelf;
             DHTableViewCell *cell = (id)[sSelf.tableView cellForRowAtIndexPath:indexPath];
             if (cell) {
                 [cell.imageStored setImage:image]; //Commenting this out relieves all lag
             }
         });
     });
 }
  

Комментарии:

1. Откуда вы вызываете этот фрагмент кода? И у каждой ячейки есть другое изображение?

2. Он вызывается в tableview:cellforindexpath:

3. Каждая ячейка имеет другое изображение.

4. Я не знаю об этом методе. Можете ли вы опубликовать весь метод. С чем это связано cellForRowAtIndexpath ? Я заметил, что вы перезваниваете cellForRowAtIndexPath в этот код, что кажется странным. Обычно вы загружаете изображения в фоновый поток, вызываемый в cellForRowAtIndexPath — и тогда у вас уже есть ссылка на ячейку

5. хорошо, я обновил код, чтобы его было легче понять. Причина, по которой я использую cellForRowAtIndexPath для получения ссылки на ячейку, заключается в том, что есть вероятность, что ячейка может оказаться вне экрана к моменту окончательной загрузки изображения. Способ работы tableviews заключается в переработке ячеек, поэтому, если я использую только ссылку на ячейку из метода, это может привести к обновлению неправильной ячейки. (если я неправильно понял, как это работает, пожалуйста, поправьте меня)

Ответ №1:

@Calimari328 Я ненавижу, если использовать это в качестве ответа, потому что на самом деле это не отвечает на ваш вопрос, но правда в том, что вам действительно нужно использовать библиотеку для достижения этой цели. например, SDWebImage

Пример:

 #import <SDWebImage/UIImageView WebCache.h>

...

- (UITableViewCell *)tableView:(UITableView *)tableView
                            cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *MyIdentifier = @"MyIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier] autorelease];
    }

    // Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    cell.textLabel.text = @"My Text";
    return cell;
}
  

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

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

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

Комментарии:

1. Это фантастическая библиотека с открытым исходным кодом, но мой проект не загружает ее из Интернета. он загружает его с диска.

2. Опять же, я могу предложить вам попробовать, только если вы прочитаете описание, в котором оно написано An asynchronous memory disk image caching with automatic cache expiration handling