将 WebView 保存为 PDF returns 空白图像?

Saving WebView to PDF returns blank image?

我正在尝试弄清楚如何将 WebView 保存为 PDF 并完全卡住,真的很感激一些帮助吗?

我在 Cocoa & Swift OSX 中执行此操作,这是我目前的代码:

import Cocoa
import WebKit

class ViewController: NSViewController {

    override func loadView() {
        super.loadView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        loadHTMLString()
    }

    func loadHTMLString() {
        let webView = WKWebView(frame: self.view.frame)
        webView.loadHTMLString("<html><body><p>Hello, World!</p></body></html>", baseURL: nil)
        self.view.addSubview(webView)
        createPDFFromView(webView, saveToDocumentWithFileName: "test.pdf")
    }

    func createPDFFromView(view: NSView, saveToDocumentWithFileName fileName: String) {
        let pdfData = view.dataWithPDFInsideRect(view.bounds)
        if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
            let documentsFileName = documentDirectories + "/" + fileName
            debugPrint(documentsFileName)
            pdfData.writeToFile(documentsFileName, atomically: false)
        }
    }

}

这很简单,我正在做的是创建一个 WebView 并向其写入一些基本的 html 内容以呈现以下内容:

然后获取视图并将其保存为 PDF 文件,但结果为空白:

我试过从 webView 和 View 中抓取内容,但没有成功。

我在这里 How to take a screenshot when a webview finished rending 发现了一个关于将 webview 保存为图像的类似问题,但到目前为止 OSX 解决方案还没有成功。

会不会是跟文档尺寸有关? 或者内容在子视图中? 也许如果您捕获了视图,您就无法捕获子视图?

有什么想法吗?

所以我有点想出了解决方法,事实证明你不能(尤其是在 OSX 上)从 WKWebView 访问和打印 webview。

您必须使用 WebView 而不是 WKWebView(我最初是从 WKWebView 开始的,因为我读过的一些文章说要使用它)。

WebView 对象与 WKWebView 对象非常相似,这非常有趣:-)

但它可以让您访问 .mainFrame 和 .frameView,您需要打印它的内容。

这是我的代码:

    let webView = WebView(frame: self.view.frame)
    let localfilePath = NSBundle.mainBundle().URLForResource(fileName, withExtension: "html");
    let req = NSURLRequest(URL: localfilePath!);
    webView.mainFrame.loadRequest(req)
    self.view.addSubview(webView)

呈现后,我添加了 1 秒的延迟,以确保内容在我打印之前已经呈现,

    // needs 1 second delay
    let delay = 1 * Double(NSEC_PER_SEC)
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
    dispatch_after(time, dispatch_get_main_queue()) {
        // works!
        let data = webView.dataWithPDFInsideRect(webView.frame)
        let doc = PDFDocument.init(data: data)
        doc.writeToFile("/Users/john/Desktop/test.pdf")

        // works!
        let printInfo = NSPrintInfo.sharedPrintInfo()
        let printOperation = NSPrintOperation(view: webView.mainFrame.frameView, printInfo: printInfo)
        printOperation.runOperation()
    }

我在这里打印它并将其另存为 PDF,以确保它在所有情况下都能正常工作。

我确定它可以改进,我讨厌延迟 hack,应该在内容完全加载后用某种回调或委托 运行 替换它。

iOS 11.0 及更高版本,Apple 提供了以下API 来捕获 WKWebView 的快照。

@available(iOS 11.0, *)
    open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)

示例用法:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

        if #available(iOS 11.0, *) {
            webView.takeSnapshot(with: nil) { (image, error) in
                //Do your stuff with image
            }
        }
    }

iOS 10 及以下,必须使用 UIWebView 来捕获快照。可以使用以下方法来实现。

func webViewDidFinishLoad(_ webView: UIWebView) {

        let image = captureScreen(webView: webView)
        //Do your stuff with image
    }

func captureScreen(webView: UIWebView) -> UIImage {
        UIGraphicsBeginImageContext(webView.bounds.size)
        webView.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

这是另一个相关的