0

Я хотел бы создать pdfReader с коллекцией. То, что я хочу, - это просмотр коллекции с эскизами PDF для отображения. Поэтому я использую это в viewDidLoad (чтобы избежать того, что он будет генерировать эскиз в коллекции, каждый раз, когда мы спускаемся вниз или вверх). Он генерируется один раз, и это без задержки:Как предварительно загрузить изображения в CollectionView, создав миниатюру PDF?

Загрузки эскиза PDF в viewDidLoad:

- (void)viewDidLoad 
... 
coverPdf = [NSMutableArray new]; 
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) { 
     // Load image on a non-ui-blocking thread 
     NSString *pdfPath = nil; 
     NSURL *pdfUrl = nil; 
     CGPDFDocumentRef pdfRef = nil; 
     NSMutableArray *arr = [NSMutableArray new]; 
     for (id cover in filePathsArray) 
     { 
      pdfPath = [categoryPath stringByAppendingPathComponent:cover]; 
      pdfUrl = [NSURL fileURLWithPath:pdfPath]; 
      pdfRef = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl); 
      [arr addObject:[self imageFromPDFWithDocumentRef:pdfRef]]; 
      NSLog(@"first process"); 

     } 
     coverPdf = [NSMutableArray arrayWithArray:arr]; 
    dispatch_sync(dispatch_get_main_queue(), ^(void) { 
     [pdfCollectionView reloadData]; 
    }); 
}); 
... 
} 

Генерации миниатюры:

- (UIImage *)imageFromPDFWithDocumentRef:(CGPDFDocumentRef)documentRef 
{ 
    CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1); 
    CGRect pageRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox); 

    UIGraphicsBeginImageContext(pageRect.size); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextTranslateCTM(context, CGRectGetMinX(pageRect),CGRectGetMaxY(pageRect)); 
    CGContextScaleCTM(context, 1, -1); 
    CGContextTranslateCTM(context, -(pageRect.origin.x), -(pageRect.origin.y)); 
    CGContextDrawPDFPage(context, pageRef); 

    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return finalImage; 
} 

Использования миниатюры:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    ListPdfCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionViewCell" forIndexPath:indexPath]; 

    cell.productLabel.text = [filePathsArray objectAtIndex:indexPath.row]; 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) { 
     // Load image on a non-ui-blocking thread 

     dispatch_sync(dispatch_get_main_queue(), ^(void) { 
      // Assign image back on the main thread 
      if ([coverPdf count] > indexPath.row) 
      { 
       cell.pdfImage.image = [coverPdf objectAtIndex:indexPath.row]; 
      } 
     }); 
    }); 

    return cell; 
} 

У меня есть две проблемы с этим методом:
- Первое, что миниатюра занимает слишком много времени, чтобы появиться. Когда он загружен, он работает хорошо.
- Вторая проблема заключается в том, что память постоянно увеличивается, и даже если я закрываю viewcontroller, и я вхожу в нее, кажется, что память не выпущена. Если я закрою viewcontroller и выйду в 9 или 10 раз, при аварии приложения.
enter image description here В заключение, как я могу создать представление коллекции, предварительно загрузив миниатюры PDF-файлов и как избежать сбоя при увеличении памяти?

Заранее спасибо.

РЕШЕНИЕ:

  • За то, что она занимает слишком много времени, чтобы появиться, я просто заменил DISPATCH_QUEUE_PRIORITY_BACKGROUND с DISPATCH_QUEUE_PRIORITY_HIGH. Это намного лучше.

  • Для утечки памяти, я использовал CGPDFDocumentRelease() функцию только в конце цикла, как это, и все работает как шарм:

    for (id cover in filePathsArray) 
        { 
         pdfPath = [categoryPath stringByAppendingPathComponent:cover]; 
         pdfUrl = [NSURL fileURLWithPath:pdfPath]; 
         pdfRef = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl); 
         [arr addObject:[self imageFromPDFWithDocumentRef:pdfRef]]; 
    
         CGPDFDocumentRelease(pdfRef);//Line added 
    
         NSLog(@"first process"); 
        } 
    

ответ

1

У меня есть плохие новости для вас , Утечка памяти это не ваша проблема, но управление IOS 10 памяти ошибка

Существует ошибка управления памятью в IOS 10.0.1 и 10.0.2 в функции CGContextDrawPDFPage().

Вы можете найти подробности здесь http://www.openradar.me/28415289

Также вы можете найти полезную дискуссию https://github.com/vfr/Reader/issues/166

В нескольких словах возможное временное решение не создавать CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1); каждый раз, но использовать один CGPDFPageRef для всех ваших PDF-файлы. Затем установите его NULL, когда вам это больше не нужно.

Создание миниатюр лаг

И с точки зрения решения для создания эскизов. Я могу только предложить не делать это в этом VC вообще, но создавать эскизы для каждого .pdf в приложении в тот момент, когда этот .pdf добавлен в приложение (или при запуске приложения в фоновом режиме, если все pdf-файлы, хранящиеся в комплекте приложения). Затем вы можете сохранить этот превью как .jpg или .png файлы с именами, равными именам PDF, или установить отношения между pdf и предварительным просмотром в любой базе данных или другом хранилище, если у вас есть это приложение. Затем просто повторно используйте этот превью в своей коллекцииView.

+0

О, отлично, я использую CGPDFDocumentRelease (pdfRef); и он отлично работает из-за ошибки. – Claudio

+0

@Claudio Это может быть очень опасно, поскольку по умолчанию 'CGPDFDocumentGetPage' возвращает объект с автореализацией (как и любой другой метод CG с семантикой Get). Поэтому, когда ошибка будет исправлена ​​Apple, ваш релиз руководства приведет к дополнительному выпуску и может привести к сбоям. –

+0

Я удалю его, когда они разрешат проблему (я думаю, что они никогда не разрешат ее лично). – Claudio

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