2016-02-02 2 views
2

Я использую coredata. Я успешно добавил изображение в свой coredata, но проблема, когда я хочу отобразить список. Я получаю эту отстающую проблему, когда прокручиваю вниз по UITableView. Я прочитал этот пост Loading image from CoreData at cellForRowAtIndexPath slows down scrolling. Я все еще получаю отставание, и теперь я пытаюсь использовать LazyLoadImage, но проблема в том, что они не используют viewdidload(). Я не знаю этого LazyLoadImage. Я хочу узнать больше о Grand Central Dispatch и о том, как это работает.UITableView отставание при загрузке изображения в coredata

Вот мой код.

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

    NSManagedObject *coreData = [self.devices objectAtIndex:indexPath.row]; 


    ImageCell *cell = (ImageCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 

    if (cell == nil) { 
     cell = [[ImageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; 
    } 


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 


     UIImage *imagex = [cache objectForKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 
     UIImage * rowImage = [UIImage imageWithData:[coreData valueForKey:@"image"]]; 
     UIImageView * myImage = [[UIImageView alloc] initWithImage:rowImage]; 
     myImage.contentMode = UIViewContentModeScaleAspectFill; 
     myImage.frame = CGRectMake(0, 0, 79, 56); 

     cell.name.text = [coreData valueForKey:@"name"]; 
     if (imagex == nil) { 

      [cache setObject:myImage.image forKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 


      imagex = [cache objectForKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 
     } 
     if(imagex){ 

      dispatch_async(dispatch_get_main_queue(), ^{ 

       if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { 
        //check that the relevant data is still required 
        UITableViewCell * correctCell = [self.tableView cellForRowAtIndexPath:indexPath]; 
        //get the correct cell (it might have changed) 
        [[correctCell imageView] setImage:imagex]; 
        [correctCell setNeedsLayout]; 
       } 
      }); 
     } 
    }); 


    return cell; 

} 

Имеет ли значение производительность, если я ставлю свой список внутри контроллера? Я не использую xib здесь.

enter image description here

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

ОБНОВЛЕНИЕ Изображения поступали с камеры, которую я снимал. Я думаю, мне нужно изменить его размер.

+0

' self.devices' ваш массив, в котором вы Лоа d tableView? – noobsmcgoobs

+0

@noobsmcgoobs да. это тот, кто хранит список данных из coredata. – user3818576

+0

Насколько велик ваш набор данных? В частности - настолько ли он настолько велик, что вам действительно нужно извлекать данные только тогда, когда вам это нужно, или вы можете хранить его в памяти? – Russell

ответ

2

Почему вы устанавливаетеNeedsLayout после setImage? Я не думаю, что это необходимо.

+0

Я просто копирую его в другое сообщение. Я удалю его – user3818576

+0

все тот же. Я получаю задержку при первой загрузке. – user3818576

1

Если у вас есть 50 записей, вы можете загрузить их все - в фоновом режиме - и заполнить self.devices изображениями. Вы можете инициировать это население в viewDidLoad или всякий раз, когда вам нужно обновить

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

В рамках загрузки данных вы должны вызвать reloadData() каждые 10 записей или около того и один раз в конце, чтобы убедиться, что вы обновляете представление таблицы, когда доступны данные.

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

+0

Проблема заключается в первом нагружении при прокрутке вниз. Я попробую ваш совет – user3818576

+0

Кстати. Размер изображения очень большой. Имеет ли значение размер изображения? – user3818576

+0

зависит от того, насколько большой! Если вы можете загрузить все 50 изображений за один раз, вы получите более высокую скорость передвижения по вашему табло.Если 50 изображений настолько велики, что загружать их все сбой устройства, то производительность будет не так хороша :-) – Russell

1

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

Ваши клетки повторно, так что я не уверен, что вам нужен этот код

if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { 
       //check that the relevant data is still required 
       UITableViewCell * correctCell = [self.tableView cellForRowAtIndexPath:indexPath]; 

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

Ваша проблема в первой загрузке. ОС кэширует изображение, когда вы используете setImage, так что после первой загрузки нет задержки, поэтому большая часть вашего кода кеширования не имеет эффекта, поскольку первая настройка изображения требует инициализации объекта, а затем ОС кэширует его.

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

+0

Да, изображения очень большие. Я все еще участвую здесь, чтобы уменьшить изображение. Я обновлю вас. спасибо – user3818576

1

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

Вы можете сохранить изображения пример кода 1. Магазин Все изображения в массиве называется imageArray

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder 
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat: @"/%@",self.projectName ]]; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) 
     [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; 


    for (int i=0; i< self.imageArray.count; i++) { 
     NSString *savedImagePath = [dataPath stringByAppendingPathComponent:[NSString stringWithFormat: @"%i.png",i ]]; 
     UIImage *image = [self.imageArray objectAtIndex:i]; 
     NSData *imageData = UIImagePNGRepresentation(image); 
     if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) 
     { 
      [[NSFileManager defaultManager] removeItemAtPath:savedImagePath error:&error]; 

     } 

    [imageData writeToFile:savedImagePath atomically:NO]; 
    // 


    } 

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

static NSString *simpleTableIdentifier = @"imageCell"; 

    NSManagedObject *coreData = [self.devices objectAtIndex:indexPath.row]; 


    ImageCell *cell = (ImageCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 

    if (cell == nil) { 
     cell = [[ImageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; 
    } 
UIImage *imagex = [cache objectForKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder 
     NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat: @"/%@",self.projectName ]]; 

    NSString * imgPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat: @"/image%@",indexPath.row]]; 
     NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imgPath]]; 

     UIImage * rowImage = [[UIImage alloc] initWithData:imgData]; 
     UIImageView * myImage = [[UIImageView alloc] initWithImage:rowImage]; 
     myImage.contentMode = UIViewContentModeScaleAspectFill; 
     myImage.frame = CGRectMake(0, 0, 79, 56); 

     cell.name.text = [coreData valueForKey:@"name"]; 
     if (imagex == nil) { 

      [cache setObject:myImage.image forKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 


      imagex = [cache objectForKey:[NSNumber numberWithUnsignedInteger:indexPath.row]]; 
     } 
+1

спасибо за этого человека. Я изучу это. другое знание здесь. Я обновлю вас. еще раз спасибо. – user3818576

0

Если вы храните фотографии, видео или аудио в базе данных (так, любой potencially большой файл), настоятельно рекомендуется использовать ссылки на них и использовать файловую систему для управления контентом, специально если вы планируют сотни, может быть, тысячи записей или больше.

Примечание. Не забудьте также загрузить файлы асинхронно.

Что нужно помнить: Когда вы запрашиваете данные все берет память ...

..

Попробуйте обходной путь:

  • Откройте ваши данные модель
  • объект, который хранит атрибут «образ»
  • выберите атрибут, который хранит изображение,
  • затем в правом меню «Data Model Ревизора»,
  • выберите:
    • «Store во Внешнюю записи файла "

это будет делать трюк :)

Смежные вопросы