UIMarkupTextPrintFormatter永远不会渲染base64图像

时间:2016-10-25 12:05:33

标签: html swift pdf webview uiprintformatter

我在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编码图像外,一切都很好。 webview或内部safari或chrome浏览器中的HTML内容本身正确显示并正确显示所有图像。但图像永远不会呈现为PDF格式。

为什么图像没有渲染,我怎样才能渲染它们?

2 个答案:

答案 0 :(得分:6)

这是因为WebKit首先将HTML解析为DOM,并在多个事件循环周期中呈现内容。因此,您不仅要等待页面DOM准备好,还要等待资源加载完成。正如您所建议的那样,您需要重构代码,以便首先加载webview,然后只导出其内容。

要确定触发导出的正确时间,您可以在Web视图中观察DOM文档的状态。有多种方法可以执行此操作,但我找到的最易读的选项是a port of an answer to a related Objective-C question:在UIWebViewDelegate实施中,按以下方式实施webViewDidFinishLoad以监控document.readyState:< / p>

    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(…)
    }

答案 1 :(得分:3)

我找到了解决方案!

导出到PDF在渲染过程完成之前发生。如果你输入一个非常小的图片,它会显示在PDF中。如果图片太大,渲染过程会花费太多时间,但PDF导出不等待渲染完成。

所以我做的工作如下:

在导出为PDF之前,我在WebView中显示HTML的结果。 WebView正在正确呈现所有内容,现在当我按下导出到PDF时,PDF正确显示内部的所有图像。

所以我猜这是一个巨大的滞后,没有办法告诉PDF Exporter等待渲染过程完成。