文章結(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)存管理,希望看到的朋友給我指出來,萬分感謝!!!