Я хотел бы создать 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 раз, при аварии приложения.
В заключение, как я могу создать представление коллекции, предварительно загрузив миниатюры 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"); }
О, отлично, я использую CGPDFDocumentRelease (pdfRef); и он отлично работает из-за ошибки. – Claudio
@Claudio Это может быть очень опасно, поскольку по умолчанию 'CGPDFDocumentGetPage' возвращает объект с автореализацией (как и любой другой метод CG с семантикой Get). Поэтому, когда ошибка будет исправлена Apple, ваш релиз руководства приведет к дополнительному выпуску и может привести к сбоям. –
Я удалю его, когда они разрешат проблему (я думаю, что они никогда не разрешат ее лично). – Claudio