iOS中提供了一个非常好的PDF解析类库,可以很方便地使用CGPDFDocumentRef读取PDF文件内容。但是由于PDF文件一般尺寸都比较大,一次性把内容展示出来,比较占内存。为了优化展示而不浪费不必要的内存消耗,可以使用视图UIView的CALayer机制,可以使用CATiledLayer把PDF页面分成好几个区域,展示哪个区域就调用哪个区域的数据,可以大大节省内存开销。对大尺寸的图像,也可以使用这种原理来处理。
首先使用CGPDFDocumentRef读取PDF文件,使用CGPDFDocumentGetPage方法获取到指定页的CGPDFPageRef。下面提供这个思路的主要代码片段:- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ CGPDFPageRef pageRef = myPageRef if (pageRef != nil && ctx != nil) { [(NSObject*)pageRef retain]; //prevent releasing while drawing CGPDFPageRetain(pageRef); CGContextRetain(ctx); CGContextSaveGState(ctx); CGRect bounding = layer.bounds; CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx)); CGContextTranslateCTM(ctx, 0.0, bounding.size.height); CGContextScaleCTM(ctx, 1.0, -1.0); CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(pageRef, kCGPDFCropBox, bounding, 0, true)); CGContextDrawPDFPage(ctx, pageRef); CGContextRestoreGState(ctx); CGContextRelease(ctx); CGPDFPageRelease(pageRef); [(NSObject*)pageRef release]; } }以上代码就显示出PDF内容了。继续完善以上代码。由于PDF读取一般速度比较慢,因此用户会有一个等待的时间,此时屏幕就会显示空白,为了弥补这个不好看的效果,可以考虑在展示层CALayer后增加一个背景图片CALayer。//设置背景层self.imageLayer = [CALayer layer];//设置层的图像 self.imageLayer.contents = (id) yourUIImage.CGImage;//将背景层添加到视图中去[self.layer addSublayer:self.imageLayer];另外,由于显示PDF的速度也不一定很快,尤其在切换PDF页面时。其实展示PDF最终希望是能够看清楚内容,如果缩放的比例大小,看不清内容的话,这种展示对用户来说也没有多少实际意义。因此可以利用这点做一些技巧性的优化,当PDF缩放比例太小时,就不要显示真正的PDF内容,而显示一个自己的图像,或者页面缩略图也行。优化上面方法drawLayer:的代码:- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ if(self.zoomScale < 2.0 ){ CGImageRef cgImage = yourUIImage.CGImage; if( cgImage != nil ) { CGContextSaveGState( context ); CGRect bounding = self.bounds; CGContextTranslateCTM(ctx, 0.0, bounding.size.height); CGContextScaleCTM(ctx, 1.0, -1.0); CGContextDrawImage( context, bounding, cgImage ); CGContextRestoreGState( context ); } }else { CGPDFPageRef pageRef = myPageRef ... }}