首页 > 解决方案 > 在 macOS 中将 WKWebView 内容转换为 PDF

问题描述

我正在尝试将 a 的内容转换为WKWebViewPDF 文件。

UIWebView被弃用之前,它是这样完成的:

webView.loadHTMLString("<h1>HELLO!</h1>", baseURL: nil)    
let pdfData = webView.mainFrame.frameView.documentView.dataWithPDF(inside: webView.mainFrame.frameView.documentView.frame)
let document = PDFDocument(data: pdfData)

我现在尝试的:

webView.loadHTMLString("<h1>HELLO!</h1>", baseURL: nil)
let pdfData = self.webViewPDF.webFrame.frameView.documentView.dataWithPDF(inside: self.webViewPDF.webFrame.frameView.documentView.frame)
let document = PDFDocument(data: pdfData)

但得到了以下错误:

[WKWebView webFrame]:发送到实例的无法识别的选择器。
[General] 引发了未捕获的异常

问题是WKWebView没有mainFrame财产...

标签: swiftmacospdfcocoawkwebview

解决方案


更新。下面的解决方案在iOS上运行良好,但我现在才注意到您正在寻找macOS解决方案。请让我知道这个解决方案是否有任何帮助......抱歉造成混淆;)


您现在可以使用该UIView.viewPrintFormatter()方法(来自UIView类):

返回接收视图的打印格式化程序。

启动打印作业时,您可以调用此方法为您的视图获取适当的视图打印格式化程序对象。您可以使用格式化程序对象在打印期间为您的视图配置页面布局选项。

例如:

import UIKit
import WebKit
import PDFKit

extension WKWebView {

    /// Exports a PDF document with this web view current contents.
    /// Only call this function when the web view has **finished** loading.
    func exportAsPDF() -> PDFDocument? {
        guard self.isLoading == false else {
            print("WKWebView still loading!")
            return nil
        }
        let pdfData = createPDFData()
        return PDFDocument(data: pdfData)
    }

    private func createPDFData() -> Data {
        let oldBounds = self.bounds

        var printBounds = self.bounds
        printBounds.size.height = scrollView.contentSize.height
        self.bounds = printBounds

        var printableRect = printBounds
        printableRect.origin = .zero        

        let printRenderer = UIPrintPageRenderer()
        printRenderer.addPrintFormatter(self.viewPrintFormatter(), startingAtPageAt: 0)
        printRenderer.setValue(NSValue(cgRect: UIScreen.main.bounds), forKey: "paperRect")
        printRenderer.setValue(NSValue(cgRect: printableRect), forKey: "printableRect")

        self.bounds = oldBounds
        return printRenderer.generatePDFData()
    }
}

并添加以下辅助方法UIPrintPageRenderer

extension UIPrintPageRenderer {

    func generatePDFData() -> Data {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
        self.prepare(forDrawingPages: NSMakeRange(0, self.numberOfPages))
        let printRect = UIGraphicsGetPDFContextBounds()

        for pdfPage in 0..<self.numberOfPages {
            UIGraphicsBeginPDFPage()
            self.drawPage(at: pdfPage, in: printRect)
        }

        UIGraphicsEndPDFContext()
        return pdfData as Data
    }
}

最后,您现在可以使用exportAsPDF()上面定义的 API 保存 PDF:

let webView: WKWebView = ...

let pdfDocument = webView.exportAsPDF()!

let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let pdfFile = docsDir.appendingPathComponent("WebViewPDF.pdf")

try! pdfDocument.write(to: pdfFile)


推荐阅读