快速和精益PDF浏览器的iPhone / iPad / iOS -提示和提示?

最近有很多关于绘制PDF的问题。

是的,你可以用UIWebView很容易地渲染PDF,但这不能给你从一个好的PDF查看器所期望的性能和功能。

你可以绘制PDF页面到CALayer到一个UIImage。苹果甚至有示例代码来展示如何绘制一个大的PDF 在可缩放UIScrollview中

但同样的问题不断出现。

用户界面图像方法:

  1. PDF在UIImage不光学
  2. CPU和内存在生成时命中 UIImagesPDFcontext 限制/阻止使用它来创建 实时渲染新的缩放级别

CATiledLayer方法:

    有很大的开销(时间) 将一个完整的PDF页面绘制到CALayer:可以看到各个瓷砖的渲染(即使有一个tileSize微调)
  1. CALayers不能提前准备 时间(显示在屏幕外).

一般来说,PDF查看器也占用大量内存。甚至监控苹果可缩放PDF示例的内存使用情况。

在我目前的项目中,我正在开发一个PDF查看器,并在一个单独的线程中呈现一个页面的UIImage(这里也有问题!),并在规模为x1时呈现它。一旦比例为>1,CATiledLayer渲染就开始了。iBooks采用了类似的重复查看方法,如果你滚动页面,你可以在不到一秒钟的时间内看到页面的低分辨率版本,然后就会出现清晰的版本。

我渲染2页页的每一面在焦点上,这样PDF图像就可以在开始绘制之前遮罩图层了。当页面距离焦点页面+2页时,页面再次被销毁。

有谁有任何见解,无论多么小或明显的提高性能/内存处理的绘图PDF ?或者这里讨论的其他问题?

< em >编辑:< / em >一些提示(来源- Luke Mcneice,VdesmedT,Matt Gallagher,Johann):

  • 尽可能将任何媒体保存到磁盘。

  • 如果在TiledLayers上渲染,请使用更大的tilesize

  • Init常用的数组用占位符对象,另一种设计方法是这一个

  • 注意,图像将比CGPDFPageRef更快地呈现

  • 使用NSOperations或GCD &提前准备页面 李。< / p > < / >
  • CGContextDrawPDFPage之前调用CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault);来减少绘图时的内存使用

  • 用docRef初始化你的NSOperations是一个坏主意(内存),将docRef包装成一个单例。

  • 当你可以取消不必要的NSOperations时,特别是当它们将使用内存时,注意不要让上下文打开!

  • 回收页面对象并销毁未使用的视图

  • 关闭任何打开的上下文,只要你不需要它们

  • 在收到内存警告时释放并重新加载DocRef和任何页面缓存

其他PDF功能:

103212 次浏览

我已经使用近似相同的方法构建了这样的应用程序,除了:

  • 我将生成的图像缓存到磁盘上,并且总是在一个单独的线程中预先生成两到三张图像。
  • 我没有使用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 & lt;快速直观/ QuickLook.h>; < /代码> < / p >

之后,在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的信息