从特定视图创建 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 文件的主要内容,如果未能解决你的问题,请参考以下文章