Convert SwiftUI View to PDF on iOS
After some thinking I came up with the idea of combining the UIKit to PDF method and SwiftUI.
At first you create your SwiftUI view, then you put into an UIHostingController. You render the HostingController on a window behind all other views and and draw its layer on a PDF.
Sample code is listed below.
func exportToPDF() {
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let outputFileURL = documentDirectory.appendingPathComponent("SwiftUI.pdf")
//Normal with
let width: CGFloat = 8.5 * 72.0
//Estimate the height of your view
let height: CGFloat = 1000
let charts = ChartsView()
let pdfVC = UIHostingController(rootView: charts)
pdfVC.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
//Render the view behind all other views
let rootVC = UIApplication.shared.windows.first?.rootViewController
rootVC?.addChild(pdfVC)
rootVC?.view.insertSubview(pdfVC.view, at: 0)
//Render the PDF
let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: 8.5 * 72.0, height: height))
do {
try pdfRenderer.writePDF(to: outputFileURL, withActions: { (context) in
context.beginPage()
pdfVC.view.layer.render(in: context.cgContext)
})
self.exportURL = outputFileURL
self.showExportSheet = true
}catch {
self.showError = true
print("Could not create PDF file: \(error)")
}
pdfVC.removeFromParent()
pdfVC.view.removeFromSuperview()
}
Create a PDF file from a specific View
From the answer of the linked question:
You render the HostingController on a window behind all other views and and draw its layer on a PDF.
That would be the first view, index 0 I presume. From the function you gave, this line looks relevant:
rootVC?.view.insertSubview(pdfVC.view, at: 0)
Replace 0
with your desired view.
How to Convert UIView to PDF within iOS?
Note that the following method creates just a bitmap of the view; it does not create actual typography.
(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}
Also make sure you import:
QuartzCore/QuartzCore.h
Related Topics
Uicollectionview - Horizontal Scroll, Horizontal Layout
After Upgrading to Xcode 11.2 from Xcode 11.1, App Crashes Due to _Uitextlayoutview
Xcode Suddenly Stopped Running Project on Hardware: "Could Not Launch Xxx.App: .. No Such File.."
Getting the Value of a Uitextfield as Keystrokes Are Entered
iOS Designated Initializers:Using Ns_Designated_Initializer
Disable Swipe Back Gesture in Swift
Is iOS Carplay API Public? How to Integrate Carplay
How to Delay a Method Call for 1 Second
How to Add 2 Buttons into the Uinavigationbar on the Right Side Without Ib
When Do I Need to Call Setneedsdisplay in iOS
iOS 6 - Viewdidunload Migrate to Didreceivememorywarning
Setneedslayout and Setneedsdisplay
iOS Convert Large Numbers to Smaller Format