【问题标题】:Convert WKWebView content to PDF in macOS在 macOS 中将 WKWebView 内容转换为 PDF
【发布时间】:2019-03-19 19:34:05
【问题描述】:

我正在尝试将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 属性...

【问题讨论】:

    标签: swift macos pdf cocoa wkwebview


    【解决方案1】:

    更新。下面的解决方案在 iOS 上运行良好,但我刚刚注意到 现在 您正在寻找 ma​​cOS 解决方案。如果这个解决方案可能有任何帮助,请告诉我......抱歉造成混淆;)


    您现在可以为此使用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)
    
    

    【讨论】:

    • 谢谢,但我不知道可可中 UIPrintPageRenderer 的等效项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多