将WebView保存为PDF会返回空白图像吗?

时间:2016-07-04 20:12:36

标签: swift macos cocoa wkwebview

我试图找出如何将WebView保存为PDF并完全卡住,真的很感激一些帮助吗?

我在Cocoa& amp; Swift on 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内容,这样就产生了这样的结果:

View

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

PDF

我试过从webView和View中抓取内容但没有快乐。

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

这可能与文档尺寸有关吗? 或者内容在子视图中? 也许如果您捕获视图,则无法捕获子视图?

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

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
    }

这是另一个相关的answer

答案 1 :(得分:1)

所以我想出了如何解决它,事实证明你不能(特别是在OSX上)从WKWebView访问和打印webview。

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

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

但它可以让您访问.mainFrame&amp; .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,这样我就可以确保它在所有情况下都能正常工作。

我确信它可以改进,我讨厌延迟黑客,应该用内容完全加载的某种回调或委托替换它。