在macOS中将WKWebView内容转换为PDF

时间:2019-03-19 19:34:06

标签: swift macos pdf cocoa wkwebview

我正在尝试将WKWebView的内容转换为PDF文件。

在弃用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]:无法识别的选择器已发送到实例。
  [一般]提出了一个未捕获的异常

问题是WKWebView没有mainFrame属性...

1 个答案:

答案 0 :(得分:0)

更新。该解决方案在 iOS 上运行良好,但我只是注意到 now 您正在寻找一种 macOS 解决方案。请让我知道该解决方案是否对您有任何帮助...对不起您的困惑;)


您现在可以使用UIView.viewPrintFormatter()类的方法UIView

  

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

     

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

例如:

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)