适用于iPhone / iPad / iOs的快速和精简PDF查看器
最近有很多关于绘制PDF的问题。
是的,您可以使用UIWebView
非常轻松地呈现PDF,但无法提供您期望从一个好的PDF查看器获得的性能和功能。
您可以将PDF页面绘制到CALayer或UIImage。 Apple甚至有示例代码来展示如何在Zoomable UIScrollview中绘制大型PDF
但同样的问题仍在继续。
UIImage方法:
UIImage
PDF不像光学UIImage
那样光学缩放。 PDFcontext
生成UIImages
的CPU和内存限制/阻止使用它来创建新的缩放级别的实时渲染。 CATiledLayer方法:
CALayer
:可以看到单个tile呈现(即使使用tileSize调整) CALayers
不能提前做好准备(脱离屏幕)。 一般来说,PDF阅读器在内存方面也相当重要。 甚至监控苹果的可缩放PDF示例的内存使用情况。
在我目前的项目中,我正在开发一个PDF查看器,并在单独的线程中呈现页面的UIImage
(这里也有问题!),并在scale为x1时呈现它。 一旦比例大于1, CATiledLayer
渲染就会启动。 iBooks采取了类似的双重处理方法,就好像您滚动页面一样,在清晰版本出现之前,您可以看到较低分辨率的页面版本不到一秒钟。
Im将页面的每一面都渲染为2焦点,这样PDF图像就可以在开始绘制图层之前对图层进行遮罩。当页面距焦点页面+2页时,页面会再次被销毁。
有没有人有任何见解,无论改善图形PDF的性能/内存处理有多么微小或明显? 或在此讨论的任何其他问题?
编辑:一些技巧(Credit Luke Mcneice,VdesmedT,Matt Gallagher,Johann):
尽可能将任何介质保存到磁盘。
如果在TiledLayers上渲染,请使用较大的tileSizes
初始化经常使用的占位符对象的数组,另一种设计方法是另一种设计方法
请注意,图像渲染速度比CGPDFPageRef
快
使用NSOperations
或GCD&Blocks提前准备页面。
调用CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault);
CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault);
在CGContextDrawPDFPage
之前减少绘图时的内存使用量
init'ing您NSOperations
与docRef是一个坏主意(内存),包裹docRef到一个单例。
取消不必要的NSOperations
当你可以的时候,特别是如果他们将要使用内存的话,要注意让上下文保持开放!
回收页面对象并销毁未使用的视图
一旦你不需要它们,关闭所有打开的上下文
在收到内存警告时释放并重新加载DocRef和任何页面缓存
其他PDF特点:
在PDF中获取链接(以及这里和这里)
了解用于链接定位的PDF Rect
转换PDF注释日期字符串
获取链接的目标(从/Dest
数组获取页码)
获取目录
文档标题和关键字
获取原始文本(以及这里和这里和这里(定位聚焦))
搜索(和这里)(不适用于所有的PDF文件(有些只显示奇怪的字符,我想这是一个编码问题,但我不确定) - 信誉BrainFeeder)
CALayer和离屏渲染 - 呈现下一页以进行快速/平滑显示
文档
示例项目
UIScrollView
, CATiledLayer
UIScrollView
, CATiledView
我使用近似相同的方法构建了这样的应用程序,除了:
UIImage
,而是在缩放为1时在图层中绘制图像。发出内存警告时,这些图块将自动释放。 每当用户开始缩放时,我都会获取CGPDFPage
并使用适当的CTM进行渲染。 在- (void)drawLayer: (CALayer*)layer inContext: (CGContextRef) context
中的代码如下所示:
CGAffineTransform currentCTM = CGContextGetCTM(context);
if (currentCTM.a == 1.0 && baseImage) {
//Calculate ideal scale
CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height;
CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);
CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor, baseImage.size.height/imageScaleFactor);
CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2, (self.bounds.size.height-imageSize.height)/2, imageSize.width, imageSize.height);
CGContextDrawImage(context, imageRect, [baseImage CGImage]);
} else {
@synchronized(issue) {
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
CGContextConcatCTM(context, pdfToPageTransform);
CGContextDrawPDFPage(context, pdfPage);
}
}
问题是,方含的对象CGPDFDocumentRef
。 我同步我访问pdfDoc
属性的部分,因为我释放它并在接收memoryWarnings时重新创建它。 看来CGPDFDocumentRef
对象做了一些内部缓存,我没有找到如何摆脱。
对于简单而有效的PDF查看器,当您只需要有限的功能时,您现在可以(iOS 4.0+)使用QuickLook框架:
首先,您需要链接到QuickLook.framework
和#import <QuickLook/QuickLook.h>;
之后,在viewDidLoad
或任何延迟初始化方法中:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
previewController.currentPreviewItemIndex = indexPath.row;
[self presentModalViewController:previewController animated:YES];
[previewController release];
从iOS 11开始 ,您可以使用称为PDFKit的本机框架来显示和操作PDF。
导入PDFKit后,您应该使用本地或远程URL初始化PDFView
并将其显示在您的视图中。
if let url = Bundle.main.url(forResource: "example", withExtension: "pdf") {
let pdfView = PDFView(frame: view.frame)
pdfView.document = PDFDocument(url: url)
view.addSubview(pdfView)
}
在Apple Developer文档中阅读有关PDFKit的更多信息。
链接地址: http://www.djcxy.com/p/36405.html上一篇: Fast and Lean PDF Viewer for iPhone / iPad / iOs
下一篇: Bit Manipulation