#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