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(…)
    }
Другие вопросы по тегам