appfrosch
appfrosch

Reputation: 1356

Swift: create pdf with WKWebView's createPdf

Edit:

having found a solution for issue 2 (and kind of getting the impression that there is no easy, out of the box solution for issue 1) I decided to close this question and rather create another one some time specifically for the pagination problem.


I have two issues with WKWebViews createPDF(configuration:completionHandler:):

  1. no pagination (I know that this issue has been brought up by others and that there seemingly is no automatic solution to this – I guess paginating would be a manual endeavour…)
  2. the html I load seems to be replacing spaces with new lines

The following code…

import SwiftUI
import WebKit

@main
struct PdfCreatorSOApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        Button("Create PDF") {
            savePdf()
        }
            .padding()
    }
    
    private func savePdf() {
        if let downloadDir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first {
            let savePath = downloadDir.appendingPathComponent("swiftPdf").appendingPathExtension("pdf")
            
            let webViewConfiguration = WKWebViewConfiguration()//do I need to set s.th. here?
            
            let webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
            
            let pdfConfiguration = WKPDFConfiguration()
            pdfConfiguration.rect = CGRect(x: 0, y: 0, width: 595.28, height: 841.89)
            
            webView.loadHTMLString(html, baseURL: nil)
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                webView.createPDF(configuration: pdfConfiguration) { result in
                    switch result {
                    
                    case .success(let data):
                        do {
                            try data.write(to: savePath)
                            print("Successfully created and saved pdf…")
                        } catch let error {
                            print("Could not _save_ pdf: \(error)")
                        }
                    case .failure(let error):
                        print("Could not create pdf: \(error)")
                    }
                }
            }
        }
    }
}

let html = """
<html>
<body>
<h1>Some Title</h1>
<p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tellus integer feugiat scelerisque varius. Nunc faucibus a pellentesque sit. Sagittis vitae et leo duis. Posuere lorem ipsum dolor sit amet consectetur. Porta non pulvinar neque laoreet suspendisse interdum. Dui faucibus in ornare quam viverra orci. Nulla facilisi etiam dignissim diam quis enim. Elementum pulvinar etiam non quam lacus suspendisse. Donec enim diam vulputate ut pharetra sit amet aliquam. Nunc mattis enim ut tellus elementum sagittis vitae. Vitae semper quis lectus nulla at volutpat diam ut. Enim eu turpis egestas pretium aenean pharetra magna ac.

    Cras sed felis eget velit aliquet sagittis id consectetur purus. Urna nunc id cursus metus aliquam eleifend mi. Interdum varius sit amet mattis vulputate enim nulla aliquet. At risus viverra adipiscing at in tellus integer feugiat. Dolor purus non enim praesent elementum facilisis leo vel fringilla. Interdum velit euismod in pellentesque massa placerat duis ultricies. Amet facilisis magna etiam tempor orci eu. Proin fermentum leo vel orci porta non pulvinar neque. Et magnis dis parturient montes nascetur ridiculus mus mauris vitae. Sagittis orci a scelerisque purus.
</p>
</body>
</html>
"""

…produces this output: enter image description here

Is there something missing in my WKWebViewConfiguration()?

Upvotes: 3

Views: 1714

Answers (1)

Nicholas Rees
Nicholas Rees

Reputation: 753

EDITED:

This is just a guess, but I don't think it's replacing spaces with newlines. It's wrapping what it thinks is a narrow web page as narrowly as possible (at each word).

Try adjusting the frame size of webView and see if that helps?

let webView = WKWebView(frame: .zero,... // per comments this didn't help.

Or try adjusting the size of the web page via CSS:

<p> <div **style='width: 600'**> lorem.... </div> // per comments this did

Upvotes: 3

Related Questions