WKWebView 不调用导航委托方法
WKWebView not calling navigation delegate methods
我正在尝试使用答案 here 将 html 文件导出为 pdf,该答案使用 WKWebView
加载 html 字符串,然后绘制从那PDF。我还需要它在 Catalyst 上工作,这就是我使用这种方法的原因。
发生的事情是 WKWebView
从未调用它的 navigationDelegate
方法。我在一堆委托方法中放了一堆 print()
语句,但我得到的唯一输出是:
::::: SET WEBVIEW
Loaded
我不知道是什么让 WKWebView
不调用它的委托方法。我也试过加载 URL 之类的 https://google.com 并且它以同样的方式失败。我什至从 webview 观察到加载进度,它正在加载内容,只是没有调用委托。
非常感谢任何帮助,我需要它来工作。
class ReportsRenderer: NSObject {
var webView: WKWebView? = nil {
didSet {
print("::::: SET WEBVIEW")
}
}
var completion: PDFCompletion!
typealias PDFCompletion = (Result<NSData, Error>) -> Void
func exportPDF(html: String, completion: @escaping PDFCompletion) throws {
self.completion = completion
webView = WKWebView()
webView?.navigationDelegate = self
let baseURL = URL(fileURLWithPath: NSTemporaryDirectory())
webView?.loadHTMLString(html, baseURL: baseURL)
print("Loaded")
}
func createPDF(_ formatter: UIViewPrintFormatter) {
print("Creating PDF")
let printPageRenderer = UIPrintPageRenderer()
printPageRenderer.addPrintFormatter(formatter, startingAtPageAt: 0)
let paperRect = CGRect(x: 0, y: 0, width: 595.2, height: 841.8)
let padding: CGFloat = 20
let printableRect = paperRect.insetBy(dx: padding, dy: padding)
printPageRenderer.setValue(printableRect, forKey: "printableRect")
printPageRenderer.setValue(paperRect, forKey: "paperRect")
printPageRenderer.footerHeight = 70
printPageRenderer.headerHeight = 20
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
for i in 0..<printPageRenderer.numberOfPages {
UIGraphicsBeginPDFPage();
printPageRenderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext();
self.completion?(.success(pdfData))
}
}
extension ReportsRenderer: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("::::: WEBVIEW NAVIGATED")
let viewPrintFormatter = webView.viewPrintFormatter()
createPDF(viewPrintFormatter)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("::::: WEBVIEW ERROR")
print(error.localizedDescription)
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("::::: WEBVIEW DIDCOMMIT NAVIGATION")
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("::::: WEBVIEW didStartProvisionalNavigation")
}
}
我在 ViewController 中这样称呼它:
do {
try ReportsRenderer().exportPDF(html: string) { (result) in
switch result {
case .success(let pdfData):
// ---- This is never called -----
print("Made the pdf data!")
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let pdfFilename = paths[0].appendingPathComponent("\(UUID().uuidString).pdf")
pdfData.write(to: pdfFilename, atomically: true)
case .failure(let error):
// ---- This is also never called -----
print("::::: Error")
print(error.localizedDescription)
}
}
} catch {
// There isn't an error here either
print("::::: Error")
print(error)
}
您需要在 ViewController
中创建 ReportsRenderer
的实例才能使其正常工作。当您在 ViewController
中创建一个实例时,它的寿命与 ViewController
的寿命一样长。在您的情况下,它会立即取消初始化。
class ViewController: UIViewController {
let reportsRenderer = ReportsRenderer()
// then...
do {
try reportsRenderer.exportPDF(html: string) { (result) in
//...
}
我正在尝试使用答案 here 将 html 文件导出为 pdf,该答案使用 WKWebView
加载 html 字符串,然后绘制从那PDF。我还需要它在 Catalyst 上工作,这就是我使用这种方法的原因。
发生的事情是 WKWebView
从未调用它的 navigationDelegate
方法。我在一堆委托方法中放了一堆 print()
语句,但我得到的唯一输出是:
::::: SET WEBVIEW
Loaded
我不知道是什么让 WKWebView
不调用它的委托方法。我也试过加载 URL 之类的 https://google.com 并且它以同样的方式失败。我什至从 webview 观察到加载进度,它正在加载内容,只是没有调用委托。
非常感谢任何帮助,我需要它来工作。
class ReportsRenderer: NSObject {
var webView: WKWebView? = nil {
didSet {
print("::::: SET WEBVIEW")
}
}
var completion: PDFCompletion!
typealias PDFCompletion = (Result<NSData, Error>) -> Void
func exportPDF(html: String, completion: @escaping PDFCompletion) throws {
self.completion = completion
webView = WKWebView()
webView?.navigationDelegate = self
let baseURL = URL(fileURLWithPath: NSTemporaryDirectory())
webView?.loadHTMLString(html, baseURL: baseURL)
print("Loaded")
}
func createPDF(_ formatter: UIViewPrintFormatter) {
print("Creating PDF")
let printPageRenderer = UIPrintPageRenderer()
printPageRenderer.addPrintFormatter(formatter, startingAtPageAt: 0)
let paperRect = CGRect(x: 0, y: 0, width: 595.2, height: 841.8)
let padding: CGFloat = 20
let printableRect = paperRect.insetBy(dx: padding, dy: padding)
printPageRenderer.setValue(printableRect, forKey: "printableRect")
printPageRenderer.setValue(paperRect, forKey: "paperRect")
printPageRenderer.footerHeight = 70
printPageRenderer.headerHeight = 20
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
for i in 0..<printPageRenderer.numberOfPages {
UIGraphicsBeginPDFPage();
printPageRenderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext();
self.completion?(.success(pdfData))
}
}
extension ReportsRenderer: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("::::: WEBVIEW NAVIGATED")
let viewPrintFormatter = webView.viewPrintFormatter()
createPDF(viewPrintFormatter)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("::::: WEBVIEW ERROR")
print(error.localizedDescription)
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("::::: WEBVIEW DIDCOMMIT NAVIGATION")
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("::::: WEBVIEW didStartProvisionalNavigation")
}
}
我在 ViewController 中这样称呼它:
do {
try ReportsRenderer().exportPDF(html: string) { (result) in
switch result {
case .success(let pdfData):
// ---- This is never called -----
print("Made the pdf data!")
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let pdfFilename = paths[0].appendingPathComponent("\(UUID().uuidString).pdf")
pdfData.write(to: pdfFilename, atomically: true)
case .failure(let error):
// ---- This is also never called -----
print("::::: Error")
print(error.localizedDescription)
}
}
} catch {
// There isn't an error here either
print("::::: Error")
print(error)
}
您需要在 ViewController
中创建 ReportsRenderer
的实例才能使其正常工作。当您在 ViewController
中创建一个实例时,它的寿命与 ViewController
的寿命一样长。在您的情况下,它会立即取消初始化。
class ViewController: UIViewController {
let reportsRenderer = ReportsRenderer()
// then...
do {
try reportsRenderer.exportPDF(html: string) { (result) in
//...
}