UIMarkupTextPrintFormatter никогда не отображает изображения base64
Я создаю PDF-файл из HTML-контента в Swift 3.0:
/**
*
*/
func exportHtmlContentToPDF(HTMLContent: String, filePath: String) {
// let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 694, height: 603));
// webView.loadHTMLString(HTMLContent, baseURL: nil);
let pdfPrinter = PDFPrinter();
let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent);
// let printFormatter = webView.viewPrintFormatter();
pdfPrinter.addPrintFormatter(printFormatter, startingAtPageAt: 0);
let pdfData = self.drawPDFUsingPrintPageRenderer(printPageRenderer: pdfPrinter);
pdfData?.write(toFile: filePath, atomically: true);
}
/**
*
*/
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData();
UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil);
printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages));
let bounds = UIGraphicsGetPDFContextBounds();
for i in 0...(printPageRenderer.numberOfPages - 1) {
UIGraphicsBeginPDFPage();
printPageRenderer.drawPage(at: i, in: bounds);
}
UIGraphicsEndPDFContext();
return data;
}
Все отображается нормально, кроме моих изображений в кодировке base64. Сам HTML-контент в веб-браузере или в браузере Safari или Chrome представлен правильно и показывает все изображения правильно. Но изображения никогда не отображаются в формате PDF.
Почему изображения не отображаются и как их получить?
2 ответа
Я нашел решение!
Экспорт в PDF происходит до завершения процесса рендеринга. Если вы вставите очень маленькую картинку, она появится в PDF. Если изображение слишком велико, процесс рендеринга занимает слишком много времени, но экспорт PDF не ожидает окончания рендеринга.
Итак, что я сделал, чтобы это заработало:
Перед экспортом в PDF я показываю Результат HTML в WebView. WebView корректно отображает все, и теперь, когда я нажимаю на экспорт в PDF, PDF отображается правильно со всеми изображениями внутри.
Так что, я полагаю, это огромная задержка, так как нет способа заставить PDF Exporter ждать завершения процесса рендеринга.
Это происходит потому, что WebKit сначала анализирует HTML-код в DOM и отображает контент в нескольких циклах цикла событий. Поэтому вам нужно подождать не только готовности DOM страницы, но и завершения загрузки ресурса. Как вы также предлагаете, вам нужно реорганизовать свой код так, чтобы сначала загружалось веб-представление, а вы только потом экспортировали его содержимое.
Чтобы определить правильное время для запуска экспорта, вы можете наблюдать за состоянием документа DOM в веб-представлении. Есть несколько способов сделать это, но наиболее читаемый вариант, который я нахожу, это порт ответа на связанный вопрос Objective C: в вашей реализации UIWebViewDelegate реализуйте webViewDidFinishLoad
следующим образом контролировать document.readyState
:
func webViewDidFinishLoad(_ webView: UIWebView) {
guard let readyState = webView.stringByEvaluatingJavaScript(from: "document.readyState"),
readyState == "complete" else
{
// document not yet parsed, or resources not yet loaded.
return
}
// This is the last webViewDidFinishLoad call --> export.
//
// There is a problem with this method if you have JS code loading more content:
// in that case -webViewDidFinishLoad can get called again still after document.readyState has already been in state 'complete' once or more.
self.exportHtmlContentToPDF(…)
}