it-swarm.com.ru

iOS ленивая загрузка настольных изображений

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    //NSLog(@"cell for row at indexpath, size - %f, current - %d", flowTable.contentSize.height, self.current);

    NSString *CellIdentifier = @"FlowCell";

    MyFlowCell *cell = (MyFlowCell *)[self.flowTable dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FlowCell" owner:nil options:nil];
       // cell = [nib objectAtIndex:0];

        for(id currentObject in nib)

        {

        if([currentObject isKindOfClass:[MyFlowCell class]])

        {
            cell = (MyFlowCell *)currentObject;

            break;
        }
        }
    }

    ImageDetails *rowItem = [self.imageData objectAtIndex:indexPath.row];

    if (!rowItem.mainImage)
    {  
       // if (self.flowTable.dragging == NO && self.flowTable.decelerating == NO)
       // {

            [self startIconDownload:rowItem forIndexPath:indexPath];

        //}

        cell.mainImage.backgroundColor = [UIColor grayColor];

    }
    else
    {

            cell.mainImage.image = rowItem.mainImage;

    }
    }


    return cell;
}


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate)
    {
      //  [self loadImagesForOnscreenRows];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //[self loadImagesForOnscreenRows];
}

Более того, я обнаружил, что в моем классе ImageDownloader NSURLConnection даже не получает ответ, пока я не уберу палец с экрана. Я пытался выяснить, почему это происходит, но я пока не добился успеха. Пожалуйста, скажите мне, если я что-то упустил.

10
Rameez Hussain

Вы можете добиться ленивой загрузки таблицы, выполнив следующие действия:

В вашем Class.h вставьте:

NSMutableDictionary *Dict_name;
BOOL isDragging_msg, isDecliring_msg;

Теперь в файле Class.m, поместите этот код в вид загрузки:

Dict_name = [[NSMutableDictionary alloc] init];

В cellForRowAtIndexPath:

if ([dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]) { 
    cell.image_profile.image=[dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
}
else
{
    if (!isDragging_msg && !isDecliring_msg)
    {
        [dicImages_msg setObject:[UIImage imageNamed:@"Placeholder.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
        [self performSelectorInBackground:@selector(downloadImage_3:) withObject:indexPath];
    }
    else
    {
        cell.image_profile.image=[UIImage imageNamed:@"Placeholder.png"];
    }
}

И для загрузки изображения функция:

-(void)downloadImage_3:(NSIndexPath *)path{
    NSAutoreleasePool *pl = [[NSAutoreleasePool alloc] init];

    NSString *str=[here Your image link for download];

    UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]]; 

    [dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"image name or image link same as cell for row"]];

    [tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

    [pl release];
}

И наконец поместите эти методы в вашем классе:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    isDragging_msg = FALSE;     
    [tableview reloadData];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    isDecliring_msg = FALSE;
    [tableview reloadData]; 
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    isDragging_msg = TRUE;
}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
    isDecliring_msg = TRUE; 
}
8
Wolverine

Обновленный ответ:

Стандартный Apple LazyTableImages имеет несколько недостатков:

  1. Он не будет пытаться получить изображения, пока прокрутка не закончится. Я понимаю, почему они решили это сделать (вероятно, не хотят извлекать изображения, которые могут прокручиваться), но это заставляет изображения появляться медленнее, чем необходимо.

  2. Это не ограничивает количество одновременных запросов некоторым разумным числом. Да, NSURLConnection будет автоматически замораживать запросы до тех пор, пока максимальное количество запросов не упадет до некоторого разумного числа, но в худшем случае вы можете фактически получить тайм-аут запросов, а не просто правильно поставить в очередь.

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

Простое решение - удалить IconDownloader и всю логику прокрутки/замедления и просто использовать категорию UIImageView из SDWebImage или AFNetworking .

Если вы собираетесь исправить это самостоятельно, потребуется немного усилий, чтобы все это правильно сделать. Но здесь приведено исполнение LazyTableImages , которое использует NSOperationQueue для обеспечения того, чтобы мы (а) ограничивали одновременные запросы; и (б) позволяет нам отменить запросы. Признаюсь, я предпочитаю вышеупомянутые реализации категории UIImageView, но я старался придерживаться структуры оригинальной LazyTableImages от Apple, одновременно исправляя недостатки, которые я перечислил выше.

9
Rob

Предполагая, что ваш UITableViewCell имеет свойство url и свойство UIImage для изображения (плюс свойство или статическое значение для очереди:

- (void) setThumbnailUrlString:(NSString *)urlString
{
    thumbnailUrlString = urlString;

    NSURL *url = [NSURL URLWithString:urlString];

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    if ( queue == nil )
    {
        queue = [[NSOperationQueue alloc] init];
    }
    [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse * resp, NSData     *data, NSError *error) 
    {
        dispatch_async(dispatch_get_main_queue(),^ 
                       {
                            if ( error == nil && data )
                            {
                                UIImage *urlImage = [[UIImage alloc] initWithData:data];
                                thumbnail.image = urlImage;
                            }
                       });
    }];
}

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

Чтобы быть корректным, блок должен проверить, соответствует ли URL-адрес ответа запрошенному URL-адресу, если изображение ячейки загружено слишком поздно, прежде чем ячейка была повторно использована для другого изображения.

1
ahwulf

Это довольно поздний ответ, но с изменениями версии iOS подход постоянно меняется.

Чтобы лениво загружать изображения, вот рекомендуемый подход:

  1. Загрузите URL-адреса всех изображений и сохраните их в свой контейнер (массив/объекты и т.д.)
  2. Запустите NSURLSessionTask (только после iOS 7), который выполняет асинхронную синхронизацию в фоновой очереди. Если вы ниже iOS 7, вы можете использовать NSURLConnection SendAsynchronousRequest API - он устарел в iOS 9, поэтому вам лучше избавиться от этого в ближайшее время.
  3. Создайте свои изображения в фоновой очереди
  4. Вернитесь в основную очередь, убедитесь, что вы получили правильный UITableViewCell, затем обновите изображение

Здесь - весь подход описан в моем уроке .

0
Nirav Bhatt

Я сделал эту структуру, которая содержит ленивый контроллер загрузки. Он прост в использовании и работает "из коробки" https://github.com/cloverstudio/CSUtils Учебное пособие можно найти здесь: http: //www.clover -studio.com/blog/using-csutils-ios-framework-for-lazy-loading-images/

0
Josip B.