Print HTML (with Images) to PDF in SwiftUI

43 Views Asked by At

I am trying to convert an existing project to SwiftUI. I create an HTML string and use it to create a PDF file. Sadly, WebKit functionality such as createPDF(configuration:completionHandler:) isn't accessible under SwiftUI. The following allows me to display the html correctly, but makePDF() throws the error "Specified target process does not exist".

struct ContentView: View {
    var body: some View {
        if let url = Bundle.main.url(forResource: "file", withExtension: "html") {
            WebView(request: URLRequest(url: url))
        }
    }   
}

struct WebView: UIViewRepresentable {
    let request: URLRequest

    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(request)
        self.myUtility(uiView: uiView)
    }
    
    func myUtility(uiView: WKWebView) {
        let pdfConfiguration = WKPDFConfiguration()
        pdfConfiguration.rect = CGRect(x: 0, y: 0, width: 810.0, height: 810.0 * 297.0 / 210.0)
                
        uiView.createPDF(configuration: pdfConfiguration) { result in
            switch result {
            case .success(let data):
                do {
                    let docFolders = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
                    guard let docFolder = docFolders.first else { return }
                    
                    let pdfURL = docFolder.appendingPathComponent("Output.pdf")
                    
                    try data.write(to: pdfURL)
                } catch {}
            case .failure:
                print(result)
            }
        }
    }
}

Taking a different approach I've tried using UIMarkupTextPrintFormatter, and I can successfully produce a PDF of text, but not images. This is a well documented issue. Some have suggested converting the image to base64 and inserting inline into the HTML string, but this doesn't work for many, including me.

I'm really surprised that this is so difficult because I would have thought that sharing a page would be quite a common requirement. If anyone has managed to make either of these two approaches work, or if there is a different approach that I haven't considered, please educate me!

0

There are 0 best solutions below