Конвертировать содержимое WKWebView в PDF в macOS

#swift #macos #pdf #cocoa #wkwebview

#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]: нераспознанный селектор, отправленный экземпляру.
[Общие сведения] Возникло неперехваченное исключение

Проблема в том, что у WKWebView него нет mainFrame свойства…

Ответ №1:

Обновить. Решение, приведенное ниже, отлично работает на iOS, но я только сейчас заметил, что вместо этого вы ищете решение для macOS. Пожалуйста, дайте мне знать, может ли это решение вообще чем-либо помочь … извините за путаницу 😉


Теперь вы можете использовать для этого UIView.viewPrintFormatter() метод (из UIView класса):

Возвращает средство форматирования печати для принимающего представления.

При запуске задания печати вы можете вызвать этот метод, чтобы получить соответствующий объект форматирования печати view для вашего представления. Вы можете использовать объект 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
    }
}

  

Наконец, теперь вы можете сохранять PDF с помощью exportAsPDF() API, определенного выше:

 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)

  

Комментарии:

1. спасибо, но я не знаю эквивалента для UIPrintPageRenderer в cocoa