从特定视图创建 PDF 文件

Posted

技术标签:

【中文标题】从特定视图创建 PDF 文件【英文标题】:Create a PDF file from a specific View 【发布时间】:2021-02-03 10:42:17 【问题描述】:

我想从视图 X 创建一个 PDF 文件。从 Alex 的问题中报告和提取的代码有效,但只创建了主视图的 PDF(视图 A)。我如何告诉他创建 View X 的 PDF?

Convert SwiftUI View to PDF on ios

// From Main View A
func savePdf() 
        let view = ViewX() // <--- This is the View I would like to transform, not linked to View A
        let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let outputFileURL = documentDirectory.appendingPathComponent("ViewX.pdf")

        let dpiScale: CGFloat = 4

        // for A5 page size inches * 72
        let pageSize = CGSize(width: 5.8 * 72, height: 8.3 * 72)
        
        let pdfVC = UIHostingController(rootView: view) 
        pdfVC.view.frame = CGRect(origin: .zero, size: pageSize * dpiScale)

        let rootVC = UIApplication.shared.windows.first?.rootViewController
        rootVC?.addChild(pdfVC)
        rootVC?.view.insertSubview(pdfVC.view, at: 0)

        let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(origin: .zero, size: pageSize))

        DispatchQueue.main.async 
            do 
                try pdfRenderer.writePDF(to: outputFileURL, withActions:  (context) in
                    context.beginPage()
                    rootVC?.view.layer.render(in: context.cgContext)
                    self.pdfURL = outputFileURL
                )
             catch 
                print("error.localizedDescription")
            
        
        pdfVC.removeFromParent()
        pdfVC.view.removeFromSuperview()
    

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。这对我有用:

import SwiftUI

func exportToPDF() 
    let outputFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("SwiftUI.pdf")
    let pageSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    
    //View to render on PDF
    let myUIHostingController = UIHostingController(rootView: ContentView())
    myUIHostingController.view.frame = CGRect(origin: .zero, size: pageSize)
    
    
    //Render the view behind all other views
    guard let rootVC = UIApplication.shared.windows.first?.rootViewController else 
        print("ERROR: Could not find root ViewController.")
        return
    
    rootVC.addChild(myUIHostingController)
    //at: 0 -> draws behind all other views
    //at: UIApplication.shared.windows.count -> draw in front
    rootVC.view.insertSubview(myUIHostingController.view, at: 0)
    
    
    //Render the PDF
    let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(origin: .zero, size: pageSize))
    DispatchQueue.main.async 
        do 
            try pdfRenderer.writePDF(to: outputFileURL, withActions:  (context) in
                context.beginPage()
                myUIHostingController.view.layer.render(in: context.cgContext)
            )
            print("wrote file to: \(outputFileURL.path)")
         catch 
            print("Could not create PDF file: \(error.localizedDescription)")
        
        
        //Remove rendered view
        myUIHostingController.removeFromParent()
        myUIHostingController.view.removeFromSuperview()
    

注意:当您尝试导出同一个视图时,请勿尝试在带有 .onAppear 的视图中使用此功能。这自然会导致无限循环。

我希望这会有所帮助!

【讨论】:

【参考方案2】:

来自链接问题的答案:

您在所有其他视图后面的窗口上呈现 HostingController,并在 PDF 上绘制其层。

这将是第一个视图,我猜是索引 0。从您提供的功能来看,这一行看起来很相关:

rootVC?.view.insertSubview(pdfVC.view, at: 0)

0 替换为您想要的视图。

【讨论】:

以上是关于从特定视图创建 PDF 文件的主要内容,如果未能解决你的问题,请参考以下文章

从UITextView创建PDF

由于 iOS 14 从 Web 视图创建 PDF 无法正常工作

如何使用 Angular 视图中的内容创建 PDF?

从模板生成PDF的最佳方法[关闭]

如何在 Swift 中的 PDF 上绘制一些东西?

如何从 Android 中的特定视图创建克隆?