目前我们正在使用 UIWebViews
显示 PDF 内容。理想情况下,我希望能够在 UITableView
中显示缩略图,而不必同时加载许多不同的 UIWebViews
,因为它们即使加载一个文档也会很慢,更不用说10个以上了!
我该如何做到这一点?
我考虑过使用 UIDocumentInteractionController
或 UIWebView
加载文档并进行屏幕截图来实现,但这意味着在显示表格之前,它们都必须被制作成缩略图。
目前我们正在使用 UIWebViews
显示 PDF 内容。理想情况下,我希望能够在 UITableView
中显示缩略图,而不必同时加载许多不同的 UIWebViews
,因为它们即使加载一个文档也会很慢,更不用说10个以上了!
我该如何做到这一点?
我考虑过使用 UIDocumentInteractionController
或 UIWebView
加载文档并进行屏幕截图来实现,但这意味着在显示表格之前,它们都必须被制作成缩略图。
在CoreGraphics
级别,苹果提供了大量绘制PDF内容的方法。据我所知,它们中没有一个被整齐地打包到UIKit
级别,因此如果您不太熟悉C层面的操作,这可能不适合您的项目,特别是在这个阶段。然而,相关函数是CGContextDrawPDFPage
;根据一般的CoreGraphics
方式,还有其他方法可以从数据源创建PDF引用,然后从PDF获取页面引用。然后,您需要处理缩放和翻译到所需的视图,并警告您需要进行水平翻转,因为PDF(和OS X)使用左下角作为原点,而iOS使用左上角。以下是我能想到的示例代码:
UIGraphicsBeginImageContext(thumbnailSize);
CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithProvider( (CGDataProviderRef)instanceOfNSDataWithPDFInside );
CGPDFPageRef pageRef = CGPDFDocumentGetPage(pdfRef, 1); // get the first page
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// ignore issues of transforming here; depends on exactly what you want and
// involves a whole bunch of normal CoreGraphics stuff that is nothing to do
// with PDFs
CGContextDrawPDFPage(contextRef, pageRef);
UIImage *imageToReturn = UIGraphicsGetImageFromCurrentImageContext();
// clean up
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdfRef);
return imageToReturn;
猜测你可能需要使用 CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox)
方法获取页面的裁剪框,然后计算如何将其缩放/移动以适应你的图像大小。
对于你的目的来说,可能更容易的方法是使用 CALayer
上的 -renderInContext:
方法(参见 QA 1703)- 获取截图的旧方法是 UIGetScreenImage
,但那实际上从未是正式的 API,似乎只有因为 RedLaser 的意外批准而被临时允许。使用 QA 中的代码可以在不必在屏幕上显示该视图的情况下从任何其他视图中获取 UIImage。这可能解决了一些关于屏幕截图的问题?但这意味着你只能支持 OS 4.x。
无论哪种情况,PDF 文件绘制速度都不快。你可能需要在后台线程上填充表格,然后绘制缩略图,当它们可用时将它们向上推动。你不能在后台线程上安全地使用 UIKit 对象,但所有的 CoreGraphics
都是安全的。
这里是一个考虑变换的示例代码。:)
NSURL* pdfFileUrl = [NSURL fileURLWithPath:finalPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfFileUrl);
CGPDFPageRef page;
CGRect aRect = CGRectMake(0, 0, 70, 100); // thumbnail size
UIGraphicsBeginImageContext(aRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage* thumbnailImage;
NSUInteger totalNum = CGPDFDocumentGetNumberOfPages(pdf);
for(int i = 0; i < totalNum; i++ ) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, aRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetGrayFillColor(context, 1.0, 1.0);
CGContextFillRect(context, aRect);
// Grab the first PDF page
page = CGPDFDocumentGetPage(pdf, i + 1);
CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, aRect, 0, true);
// And apply the transform.
CGContextConcatCTM(context, pdfTransform);
CGContextDrawPDFPage(context, page);
// Create the new UIImage from the context
thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
//Use thumbnailImage (e.g. drawing, saving it to a file, etc)
CGContextRestoreGState(context);
}
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdf);
static func getThumbnailForPDF(_ urlString:String, pageNumber:Int) -> UIImage? {
let bundle = Bundle.main
let path = bundle.path(forResource: urlString, ofType: "pdf")
let pdfURL = URL(fileURLWithPath: path!)
let pdf = CGPDFDocument(pdfURL as CFURL )!
let page = pdf.page(at: pageNumber)!
let rect = CGRect(x: 0, y: 0, width: 100.0, height: 70.0) //Image size here
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()!
context.saveGState()
context.translateBy(x: 0, y: rect.height)
context.scaleBy(x: 1.0, y: -1.0)
context.setFillColor(gray: 1.0, alpha: 1.0)
context.fill(rect)
let pdfTransform = page.getDrawingTransform(CGPDFBox.mediaBox, rect: rect, rotate: 0, preserveAspectRatio: true)
context.concatenate(pdfTransform)
context.drawPDFPage(page)
let thumbImage = UIGraphicsGetImageFromCurrentImageContext()
context.restoreGState()
UIGraphicsEndImageContext()
return thumbImage
}
PDFPage
类中有一个名为thumbnail
的方法可供使用。该方法适用于iOS11及以上版本,并且只需编写几行代码即可完成工作。下面是一个简单的方法,用于生成给定页面在PDFDocument
中的缩略图。func makeThumbnail(pdfDocument: PDFDocument?, page: Int) -> UIImage? {
return pdfDocument?.page(at: page)?.thumbnail(of: CGSize(width: 40, height: 40), for: .artBox)
}
很不幸,它缺少官方文档(请参见https://developer.apple.com/documentation/pdfkit/pdfpage/2869834-thumbnail)。但是,在代码中对于PDFPage
有一些可访问的注释。