如何通过生成pdf的缩略图来预装CollectionView中的图像?

时间:2017-01-25 10:04:50

标签: ios objective-c xcode uicollectionview uicollectionviewcell

我想创建一个带有collectionview的pdfReader。我想要的是有一个带有pdf缩略图的集合视图来显示。所以我在viewDidLoad中使用它(以避免每次我们向下或向上时它将在集合视图中生成缩略图)。它生成一次,没有滞后:

在viewDidLoad中加载pdf的缩略图:

- (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;
}

我对这种方法有两个问题:
- 第一个是缩略图占用太多时间。加载时,效果很好 - 第二个问题是,内存不断增加,即使我关闭了视图控制器,我进入它,似乎内存没有被释放。如果我关闭视图控制器并进入9或10次,如果崩溃应用程序。
enter image description here 总之,如何通过提前加载pdfs的缩略图来创建集合视图,以及如何避免内存增加导致崩溃?

提前致谢。

解决方案:

  • 由于需要花费太多时间才能出现,我只是用DISPATCH_QUEUE_PRIORITY_HIGH替换了DISPATCH_QUEUE_PRIORITY_BACKGROUND。它好多了。

  • 对于内存泄漏,我在循环结束时使用了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 个答案:

答案 0 :(得分:1)

我有个坏消息。内存泄漏不是你的问题,而是iOS 10内存管理错误

  

CGContextDrawPDFPage()函数中的iOS 10.0.1和10.0.2中存在内存管理错误。

您可以在http://www.openradar.me/28415289

找到详细信息

此外,您可以找到有用的讨论https://github.com/vfr/Reader/issues/166

简而言之,可能的解决方法是不创建 CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1); 每次但对所有pdf文件使用一个CGPDFPageRef。然后在不再需要它时将其设置为NULL。

创建缩略图延迟

就创建缩略图的解决方案而言。我只能建议不要在这个VC中完成它,而是在将.pdf添加到应用程序时(或者如果所有pdf存储在应用程序包中的应用程序启动时)在应用程序中为每个.pdf创建缩略图)。然后,您可以将此预览保存为名称等于pdf名称的.jpg或.png文件,或者在任何数据库或其他存储中设置pdf和预览之间的关系(如果您已在应用程序中使用它)。 然后只需在collectionView中重复使用此预览。