在macOS中将WKWebView内容转换为PDF

4
我将翻译以下内容:

我正在尝试将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]: 无法识别的选择子被发送到实例。
[General] 发生了一个未捕获的异常

问题在于 WKWebView 没有 mainFrame 属性...

1个回答

2
更新。下面的解决方案在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)


谢谢,但我不知道Cocoa中UIPrintPageRenderer的等效物。 - user3722523

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接