UIMarkupTextPrintFormatter 从不渲染 base64 图像
UIMarkupTextPrintFormatter never renders base64 images
我正在用 swift 3.0 中的 html 内容创建一个 pdf 文件:
/**
*
*/
func exportHtmlContentToPDF(HTMLContent: String, filePath: String) {
// let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 694, height: 603));
// webView.loadHTMLString(HTMLContent, baseURL: nil);
let pdfPrinter = PDFPrinter();
let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent);
// let printFormatter = webView.viewPrintFormatter();
pdfPrinter.addPrintFormatter(printFormatter, startingAtPageAt: 0);
let pdfData = self.drawPDFUsingPrintPageRenderer(printPageRenderer: pdfPrinter);
pdfData?.write(toFile: filePath, atomically: true);
}
/**
*
*/
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData();
UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil);
printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages));
let bounds = UIGraphicsGetPDFContextBounds();
for i in 0...(printPageRenderer.numberOfPages - 1) {
UIGraphicsBeginPDFPage();
printPageRenderer.drawPage(at: i, in: bounds);
}
UIGraphicsEndPDFContext();
return data;
}
除了我的 base64 编码图像外,一切都很好。 HTML 内容本身在 webview 或内部 safari 或 chrome 浏览器中正确呈现并正确显示所有图像。但是图像永远不会渲染成 pdf。
为什么图像没有被渲染,我怎样才能让它们被渲染?
我找到了解决方案!
导出为 PDF 发生在渲染过程完成之前。如果您放入一张非常小的图片,它就会显示在 PDF 中。如果图片太大,渲染过程会花费太多时间,但 PDF 导出不会等待渲染完成。
所以我做了以下工作:
在导出为 PDF 之前,我在 WebView 中显示了 HTML 的结果。 WebView 正确呈现所有内容,现在当我按下导出为 PDF 时,PDF 正确显示,其中包含所有图像。
所以我想这是一个巨大的滞后,无法告诉 PDF Exporter 等待渲染过程完成。
发生这种情况是因为 WebKit 首先将 HTML 解析为 DOM,并在多个事件循环周期中呈现内容。因此,您不仅需要等待页面 DOM 准备就绪,还需要等待资源加载完成。正如您还建议的那样,您需要重构代码,以便首先加载 webview,然后才导出其内容。
要确定触发导出的正确时间,您可以在 Web 视图中观察 DOM 文档的状态。有多种方法可以做到这一点,但我发现最易读的选项是 a port of an answer to a related Objective-C question: in your UIWebViewDelegate implementation, implement webViewDidFinishLoad
in the following way to monitor document.readyState
:
func webViewDidFinishLoad(_ webView: UIWebView) {
guard let readyState = webView.stringByEvaluatingJavaScript(from: "document.readyState"),
readyState == "complete" else
{
// document not yet parsed, or resources not yet loaded.
return
}
// This is the last webViewDidFinishLoad call --> export.
//
// There is a problem with this method if you have JS code loading more content:
// in that case -webViewDidFinishLoad can get called again still after document.readyState has already been in state 'complete' once or more.
self.exportHtmlContentToPDF(…)
}
我正在用 swift 3.0 中的 html 内容创建一个 pdf 文件:
/**
*
*/
func exportHtmlContentToPDF(HTMLContent: String, filePath: String) {
// let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 694, height: 603));
// webView.loadHTMLString(HTMLContent, baseURL: nil);
let pdfPrinter = PDFPrinter();
let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent);
// let printFormatter = webView.viewPrintFormatter();
pdfPrinter.addPrintFormatter(printFormatter, startingAtPageAt: 0);
let pdfData = self.drawPDFUsingPrintPageRenderer(printPageRenderer: pdfPrinter);
pdfData?.write(toFile: filePath, atomically: true);
}
/**
*
*/
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData();
UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil);
printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages));
let bounds = UIGraphicsGetPDFContextBounds();
for i in 0...(printPageRenderer.numberOfPages - 1) {
UIGraphicsBeginPDFPage();
printPageRenderer.drawPage(at: i, in: bounds);
}
UIGraphicsEndPDFContext();
return data;
}
除了我的 base64 编码图像外,一切都很好。 HTML 内容本身在 webview 或内部 safari 或 chrome 浏览器中正确呈现并正确显示所有图像。但是图像永远不会渲染成 pdf。
为什么图像没有被渲染,我怎样才能让它们被渲染?
我找到了解决方案!
导出为 PDF 发生在渲染过程完成之前。如果您放入一张非常小的图片,它就会显示在 PDF 中。如果图片太大,渲染过程会花费太多时间,但 PDF 导出不会等待渲染完成。
所以我做了以下工作:
在导出为 PDF 之前,我在 WebView 中显示了 HTML 的结果。 WebView 正确呈现所有内容,现在当我按下导出为 PDF 时,PDF 正确显示,其中包含所有图像。
所以我想这是一个巨大的滞后,无法告诉 PDF Exporter 等待渲染过程完成。
发生这种情况是因为 WebKit 首先将 HTML 解析为 DOM,并在多个事件循环周期中呈现内容。因此,您不仅需要等待页面 DOM 准备就绪,还需要等待资源加载完成。正如您还建议的那样,您需要重构代码,以便首先加载 webview,然后才导出其内容。
要确定触发导出的正确时间,您可以在 Web 视图中观察 DOM 文档的状态。有多种方法可以做到这一点,但我发现最易读的选项是 a port of an answer to a related Objective-C question: in your UIWebViewDelegate implementation, implement webViewDidFinishLoad
in the following way to monitor document.readyState
:
func webViewDidFinishLoad(_ webView: UIWebView) {
guard let readyState = webView.stringByEvaluatingJavaScript(from: "document.readyState"),
readyState == "complete" else
{
// document not yet parsed, or resources not yet loaded.
return
}
// This is the last webViewDidFinishLoad call --> export.
//
// There is a problem with this method if you have JS code loading more content:
// in that case -webViewDidFinishLoad can get called again still after document.readyState has already been in state 'complete' once or more.
self.exportHtmlContentToPDF(…)
}