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

时间:2022-08-20 00:25:47

I would like to create a pdfReader with a collectionview. What I want is to have a collectionview with Thumbnails of the pdf to display. So I use this in the viewDidLoad (to avoid the fact that it will generate the thumbnail in the collectionview each time we go down or up). It is generated one time, and it is without lag :

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

Loading the thumbnail of the pdf in 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];
    });
});
...
}

Generating the thumbnail:

生成缩略图:

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

Using the thumbnail:

使用缩略图:

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

I have two problems with that method :
- The first one is that the thumbnail is taking too much time to appear. When it is loaded, it works well.
- The second problem, is that the memory is continually increasing and even if I close the viewcontroller, and I come in it, it seems that the memory is not released. If I close the viewcontroller and come in 9 or 10 times, if crash the app.
如何通过生成pdf的缩略图来预装CollectionView中的图像? In conclusion, how can I create a collection view by loading the thumbnails of the pdfs in advance and how to avoid a crash with the memory increasing ?

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

Thanks in advance.

提前致谢。

SOLUTION :

解决方案

  • For the fact that it takes too much time to appear, I just replaced the DISPATCH_QUEUE_PRIORITY_BACKGROUND with the DISPATCH_QUEUE_PRIORITY_HIGH. It is much better.

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

  • For the memory leak, I used the CGPDFDocumentRelease() function just at the end of the loop like this, and all works like a charm :

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

#1


1  

I have bad news for you. Memory leak is not your problem but iOS 10 memory management bug

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

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

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

You can find details here http://www.openradar.me/28415289

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

Also you can find useful this discussion https://github.com/vfr/Reader/issues/166

你也可以找到有用的讨论https://github.com/vfr/Reader/issues/166

In few words possible workaround is not to create CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1); each time but use one CGPDFPageRef for all of your pdf files. Then set it NULL when you not needs it anymore.

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

Creating thumbnails lag

创建缩略图滞后

And in terms of solution for creating thumbnails. I can only suggest not to do it in this VC at all but create thumbnail for each .pdf in the app at the moment when this .pdf added to the app (or on app launch in background service if all pdfs stored in the app bundle). Then you can save this previews as .jpg or .png files with names equal to pdf names or set relationships between pdf and preview in any database or other storage if you have it in your app. Then just reuse this previews in your collectionView.

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

#1


1  

I have bad news for you. Memory leak is not your problem but iOS 10 memory management bug

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

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

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

You can find details here http://www.openradar.me/28415289

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

Also you can find useful this discussion https://github.com/vfr/Reader/issues/166

你也可以找到有用的讨论https://github.com/vfr/Reader/issues/166

In few words possible workaround is not to create CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1); each time but use one CGPDFPageRef for all of your pdf files. Then set it NULL when you not needs it anymore.

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

Creating thumbnails lag

创建缩略图滞后

And in terms of solution for creating thumbnails. I can only suggest not to do it in this VC at all but create thumbnail for each .pdf in the app at the moment when this .pdf added to the app (or on app launch in background service if all pdfs stored in the app bundle). Then you can save this previews as .jpg or .png files with names equal to pdf names or set relationships between pdf and preview in any database or other storage if you have it in your app. Then just reuse this previews in your collectionView.

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