ios - 如何通过生成 pdf 的缩略图来预加载 CollectionView 中的图像?

标签 ios objective-c xcode uicollectionview uicollectionviewcell

我想创建一个带有 Collection View 的 pdfReader。我想要的是有一个带有 pdf 缩略图的 Collection View 来显示。所以我在 viewDidLoad 中使用它(以避免每次我们向下或向上时它都会在 collectionview 中生成缩略图)。一次性生成,无延迟:

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

我有两个问题:
- 第一个是缩略图显示时间过长。加载后,它运行良好。
- 第二个问题,是内存在不断增加,即使我关闭 View Controller ,我进来了,似乎内存没有释放。如果我关闭 View Controller 并进入 9 或 10 次,如果应用程序崩溃。
enter image description here 总之,如何通过预先加载pdf的缩略图来创建 Collection View 以及如何避免随着内存增加而崩溃?

提前致谢。

解决方案:

  • 由于显示时间太长,我只是将 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"); 
        }
    

最佳答案

我有坏消息要告诉你。内存泄漏不是你的问题,而是 iOS 10 内存管理 bug

There is a memory management bug in iOS 10.0.1 and 10.0.2 in the CGContextDrawPDFPage() function.

您可以在此处找到详细信息http://www.openradar.me/28415289

您还可以发现此讨论很有用https://github.com/vfr/Reader/issues/166

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

创建缩略图滞后

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

关于ios - 如何通过生成 pdf 的缩略图来预加载 CollectionView 中的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41848619/

相关文章:

iphone - iOS 4 的规避截图

ios - 发送帖子请求 IOS 7

ios - 如何将自定义框架(GitHub 的 Mantle)包含到我的 iOS 6 项目中?

xcode - 我怎样才能摆脱错误消息 "Ambiguous use of internal linkage declaration ' .. .' defined in multiple modules"

ios - 在不重启应用程序的情况下更改 iOS 中的应用程序语言

iPhone GPS - 未收到有效的位置更新

objective-c - 当我将 C 数组传递给 Objective-C 方法时,让该方法将数组复制到堆内存是否足够?

ios - Collectionview 网格在网格的每个角落都有圆角

swift - 修复插入 "as! PFUserResultBlock"

ios - 从 UIObject 移除 UIGesturerecognizer