CoreGraphics之瀏覽和生成PDF文件詳解

文章結(jié)構(gòu)

  • 加載并瀏覽PDF文件
  • 圖片生成PDF文件
  • demo代碼解釋
  • 總結(jié)

加載并瀏覽PDF文件

  • 思路:加載pdf文件,一頁一頁繪制到自己的自定義控件中,然后可以把這些控件放到網(wǎng)格或者UIPageViewController中進(jìn)行滑動顯示。

第一步:獲取表示pdf文件的CGPDFDocumentRef對象。

為了能夠讀取pdf文件的信息,我們需要把pdf加載到一個CGPDFDocumentRef對象中,可以通過兩個方法生成該對象,如下代碼:

CGPDFDocumentRef __nullable CGPDFDocumentCreateWithProvider(
    CGDataProviderRef cg_nullable provider);
CGPDFDocumentRef __nullable CGPDFDocumentCreateWithURL(
    CFURLRef cg_nullable url);

第二步:檢查pdf文件是否加密。

使用以下接口檢查是否加密

bool CGPDFDocumentIsEncrypted(CGPDFDocumentRef cg_nullable document);

如果是加密的pdf文件則需要通過以下接口解密

 bool CGPDFDocumentUnlockWithPassword(
    CGPDFDocumentRef cg_nullable document, const char *  password);

否則無法進(jìn)行下一步。

第三步:獲取表示一頁pdf的對象CGPDFPageRef。

通過以下代碼獲取CGPDFPageRef對象

CGPDFPageRef __nullable CGPDFDocumentGetPage(
    CGPDFDocumentRef cg_nullable document, size_t pageNumber);

注意:該接口最后一個參數(shù)表示第幾頁,并且從1開始。

第四步:創(chuàng)建一個映射變換,映射pdf的box到你指定的矩形區(qū)域內(nèi)。

通過如下接口創(chuàng)建一個映射變換

CGAffineTransform CGPDFPageGetDrawingTransform(
    CGPDFPageRef cg_nullable page, CGPDFBox box, CGRect rect, int rotate,
    bool preserveAspectRatio);

以上接口的第三個參數(shù)表示你想要繪制的pdf在什么區(qū)域內(nèi),一般設(shè)置self.bounds表示布滿整個繪制上下文,可以修改該參數(shù)看看相對應(yīng)的效果;第四個參數(shù)表示旋轉(zhuǎn)角度,第五個參數(shù)表示是否等比例繪制你的pdf文件。
如果少了這一步,則文件過大情況下,文件內(nèi)容顯示會超出屏幕導(dǎo)致 顯示不全。

注意:CGPDFPageGetDrawingTransform方法的官方文檔原文如下:

creates an affine transform by mapping a box in a PDF page to a rectangle you specify.

通過

void CGContextConcatCTM(CGContextRef cg_nullable c,
    CGAffineTransform transform);

把映射變換合成到上下文中。

第五部:繪制pdf文件。

通過以下接口繪制pdf文件到自己的控件中

void CGContextDrawPDFPage(CGContextRef cg_nullable c,
    CGPDFPageRef cg_nullable page);

其實核心代碼就是CGContextDrawPDFPage該API,通過該API所需的參數(shù)一步步逆向往上推導(dǎo),就不會感到迷茫。


第六步:使用網(wǎng)格或者UIPageViewController瀏覽pdf。

怎么使用這兩個就不多說了,不會的自學(xué)。
這里說下不同點,使用網(wǎng)格的話,如果每個網(wǎng)格之間有間隔,則越往后滑動UI就越難看,效果如下:


如果每頁之間不使用間隔的話,可以使用網(wǎng)格,如果每頁之間有間隔的話,使用網(wǎng)格瀏覽到目前為止我沒有想到解決以上問題的方法,要是有解決方法可以給我留言。

圖片生成PDF文件

  • 思路:給pdf設(shè)置附加信息,如作者、是否加密等信息;設(shè)置頁面信息,如pdf的box信息等,在API文檔里都有說明;獲取pdf上下文環(huán)境,繪制pdf。

第一步:生成pdf上下文環(huán)境。

通過以下API創(chuàng)建pdf的上下文環(huán)境

CGContextRef __nullable CGPDFContextCreateWithURL(CFURLRef cg_nullable url,
  const CGRect * __nullable mediaBox, CFDictionaryRef __nullable auxiliaryInfo);

注意:還有另外一個方法CGPDFContextCreate創(chuàng)建。
第一個參數(shù)表示生成完成后保存pdf文件的路徑,第二個參數(shù)表示繪制pdf區(qū)域,第三個參數(shù)表示pdf的附件信息,是一個字典,相關(guān)的key在接口文檔里說明。

第二步:繪制pdf。

通過以下兩個接口開始繪制和結(jié)束pdf。

void CGPDFContextBeginPage(CGContextRef cg_nullable context,
  CFDictionaryRef __nullable pageInfo);
void CGPDFContextEndPage(CGContextRef cg_nullable context);

這兩個api表示開始和結(jié)束,并且必須是成對搭配使用的,在這兩個api之間繪制想要的內(nèi)容。

這里說明的是把圖片轉(zhuǎn)換成pdf文件,所以使用到以下API

void CGContextDrawImage(CGContextRef cg_nullable c, CGRect rect,
    CGImageRef cg_nullable image);

注意:在生成CGImageRef對象的時候,如果是通過以下兩個接口生成的話,必須根據(jù)圖片的格式類型使用正確的API,否則繪制不出來。

CGImageRef __nullable CGImageCreateWithJPEGDataProvider(
    CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode,
    bool shouldInterpolate,
    CGColorRenderingIntent intent);
CGImageRef __nullable CGImageCreateWithPNGDataProvider(
    CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode,
    bool shouldInterpolate,
    CGColorRenderingIntent intent);

也可以使用ImageIO框架創(chuàng)建CGImageRef對象,不需要關(guān)心圖片的格式類型,代碼如下:

- (CGImageRef)CGImageWithName:(NSString *)imageName{
    
    NSURL *url = [[NSBundle mainBundle] URLForResource:imageName withExtension:nil];
    CFURLRef cfImageURL = (__bridge_retained CFURLRef)url;
    CGImageSourceRef imageSource = CGImageSourceCreateWithURL(cfImageURL, NULL);
    CGImageRef cgimge = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
    CFRelease(cfImageURL);
    CFRelease(imageSource);
    return cgimge;
}

demo代碼解釋

網(wǎng)格瀏覽demo文件夾路徑:PDF->CollectionViewWay。
UIPageViewController demo文件夾路徑:PDF->PageVC。
圖片生成pdf文件demo文件夾路徑:PDF->ConvertToPDF。
猛戳Demo,謝謝你的閱讀,如發(fā)現(xiàn)錯誤請給我留言,謝謝!
如果喜歡就給個贊??吧!

總結(jié)

在把圖片轉(zhuǎn)化成PDF時候(工程里的PDF->ConvertToPDF),出現(xiàn)CFDictionary的內(nèi)存泄漏,如下圖:


看代碼沒看出哪里沒有不正確使用的內(nèi)存管理,希望看到的朋友給我指出來,萬分感謝!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。