Hay muchos recursos sobre cómo mostrar un PDF en una aplicación UIView
. En lo que estoy trabajando ahora es en crear un PDF a partir de UIViews
.
Por ejemplo, tengo una UIView
, con subvistas como Textviews, UILabels
, UIImages
, así que ¿cómo puedo convertir un grande UIView
en su conjunto incluyendo todas sus subvistas y subsubviews a un PDF?
He comprobado la referencia de iOS de Apple . Sin embargo, solo habla de escribir fragmentos de texto / imagen en un archivo PDF.
El problema al que me enfrento es que el contenido que quiero escribir en un archivo como PDF es mucho. Si los escribo en el PDF pieza por pieza, será un gran trabajo por hacer. Por eso estoy buscando una forma de escribir UIViews
en PDF o incluso en mapas de bits.
Probé el código fuente que copié de otro Q / A dentro de Stack Overflow. Pero solo me da un PDF en blanco con el UIView
tamaño de los límites.
-(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();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView drawRect:aView.bounds];
// 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);
}
Además, si alguien está interesado, aquí está el código Swift 3:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String) { let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil) UIGraphicsBeginPDFPage() guard let pdfContext = UIGraphicsGetCurrentContext() else { return } aView.layer.render(in: pdfContext) UIGraphicsEndPDFContext() if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first { let documentsFileName = documentDirectories + "/" + fileName debugPrint(documentsFileName) pdfData.write(toFile: documentsFileName, atomically: true) } }
fuente
Si alguien está interesado, aquí está el código Swift 2.1:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String) { let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil) UIGraphicsBeginPDFPage() guard let pdfContext = UIGraphicsGetCurrentContext() else { return } aView.layer.renderInContext(pdfContext) UIGraphicsEndPDFContext() if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first { let documentsFileName = documentDirectories + "/" + fileName debugPrint(documentsFileName) pdfData.writeToFile(documentsFileName, atomically: true) } }
fuente
completion: (success: Bool) -> ()
para los casos de devolución de guardiaUna forma súper fácil de crear un PDF desde UIView es usar la extensión UIView
Rápido 4.2
extension UIView { // Export pdf from Save pdf in drectory and return pdf file path func exportAsPdfFromView() -> String { let pdfPageFrame = self.bounds let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, pdfPageFrame, nil) UIGraphicsBeginPDFPageWithInfo(pdfPageFrame, nil) guard let pdfContext = UIGraphicsGetCurrentContext() else { return "" } self.layer.render(in: pdfContext) UIGraphicsEndPDFContext() return self.saveViewPdf(data: pdfData) } // Save pdf file in document directory func saveViewPdf(data: NSMutableData) -> String { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let docDirectoryPath = paths[0] let pdfPath = docDirectoryPath.appendingPathComponent("viewPdf.pdf") if data.write(to: pdfPath, atomically: true) { return pdfPath.path } else { return "" } } }
Crédito: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/
fuente
Con Swift 5 / iOS 12, puede combinar
CALayer
elrender(in:)
método deUIGraphicsPDFRenderer
' con el método de 'writePDF(to:withActions:)
para crear un archivo PDF a partir de unaUIView
instancia.El siguiente código de muestra de Playground muestra cómo usar
render(in:)
ywritePDF(to:withActions:)
:import UIKit import PlaygroundSupport let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) view.backgroundColor = .orange let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60)) subView.backgroundColor = .magenta view.addSubview(subView) let outputFileURL = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("MyPDF.pdf") let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds) do { try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in context.beginPage() view.layer.render(in: context.cgContext) }) } catch { print("Could not create PDF file: \(error)") }
Nota: para poder usarlo
playgroundSharedDataDirectory
en su área de juegos, primero debe crear una carpeta llamada "Datos compartidos de juegos" en la carpeta "Documentos" de macOS.La
UIViewController
implementación completa de la subclase a continuación muestra una forma posible de refactorizar el ejemplo anterior para una aplicación iOS:import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) view.backgroundColor = .orange let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60)) subView.backgroundColor = .magenta view.addSubview(subView) createPDF(from: view) } func createPDF(from view: UIView) { let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let outputFileURL = documentDirectory.appendingPathComponent("MyPDF.pdf") print("URL:", outputFileURL) // When running on simulator, use the given path to retrieve the PDF file let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds) do { try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in context.beginPage() view.layer.render(in: context.cgContext) }) } catch { print("Could not create PDF file: \(error)") } } }
fuente
Esto generará PDF desde UIView y abrirá el cuadro de diálogo de impresión, objetivo C. Adjuntar
- (IBAction)PrintPDF:(id)sender
a su botón en la pantalla. Agregar#import <QuartzCore/QuartzCore.h>
marcoArchivo H
@interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate> { UIPrintInteractionController *printController; } - (IBAction)PrintPDF:(id)sender;
Archivo M
-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename { NSMutableData *pdfData = [NSMutableData data]; UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil); UIGraphicsBeginPDFPage(); CGContextRef pdfContext = UIGraphicsGetCurrentContext(); [aView.layer renderInContext:pdfContext]; UIGraphicsEndPDFContext(); NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); NSString* documentDirectory = [documentDirectories objectAtIndex:0]; NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename]; NSString *file = [documentDirectory stringByAppendingPathComponent:@"yourPDF.pdf"]; NSURL *urlPdf = [NSURL fileURLWithPath: file]; [pdfData writeToFile:documentDirectoryFilename atomically:YES]; NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename); } - (IBAction)PrintPDF:(id)sender { [self createPDFfromUIView:self.view saveToDocumentsWithFileName:@"yourPDF.pdf"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourPDF.pdf"]; NSData *myData = [NSData dataWithContentsOfFile: path]; UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; if(pic && [UIPrintInteractionController canPrintData: myData] ) { pic.delegate = self; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = [path lastPathComponent]; printInfo.duplex = UIPrintInfoDuplexLongEdge; pic.printInfo = printInfo; pic.showsPageRange = YES; pic.printingItem = myData; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) { //self.content = nil; if(!completed && error){ NSLog(@"Print Error: %@", error); } }; [pic presentAnimated:YES completionHandler:completionHandler]; } }
fuente
No sé por qué, pero la respuesta de casilic me deja una pantalla en blanco en iOS6.1. El siguiente código funciona.
-(NSMutableData *)createPDFDatafromUIView:(UIView*)aView { // 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(); return pdfData; } -(NSString*)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename { // Creates a mutable data object for updating with binary data, like a byte array NSMutableData *pdfData = [self createPDFDatafromUIView:aView]; // 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); return documentDirectoryFilename; }
fuente