2011-03-26 12 views
76

Hay muchos recursos sobre cómo mostrar un PDF en la aplicación UIView. En lo que estoy trabajando ahora es crear un PDF desde UIViews.¿Cómo convertir UIView a PDF dentro de iOS?

Por ejemplo, tengo un UIView, con subvistas como Textviews, UILabels, UIImages, así que ¿cómo puedo convertir un gran UIView en su conjunto incluyendo todas sus subvistas y subsubviews a un PDF?

He comprobado Apple's iOS reference. Sin embargo, solo se trata 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 al PDF pieza por pieza, va a ser un gran trabajo hacerlo. Es por eso que estoy buscando una forma de escribir UIViews en archivos PDF o incluso mapas de bits.

He intentado con el código fuente que he copiado de otra Q/A dentro de Stack Overflow. Pero solo me da un PDF en blanco con el tamaño de límites UIView.

-(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); 
} 

Por favor ayuda. Gracias.

Respuesta

112

Tenga en cuenta que el siguiente método crea solo un mapa de bits de la vista; no crea una tipografía real.

(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); 
} 

También asegúrese de que la importación: QuartzCore/QuartzCore.h

+2

+1 Fui a través de varios mensajes sobre la generación de pdf antes de encontrar una solución tan simple. –

+6

Quería hacer lo mismo y su método parece funcionar bien, pero su calidad es muy baja. ¿Yo me perdí algo? – iEamin

+6

Sospecho que la calidad es bastante baja porque está tomando el UIView y convirtiéndolo en un ráster, mientras que los otros métodos de representación de texto e imágenes los preservan directamente como vectores en el archivo PDF. – joshaidan

-4

No sé por qué, pero la respuesta de casilic me da pantalla en blanco en iOS6.1. El código a continuación 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; 
} 
+15

Este es el mismo código exacto que mi respuesta acaba de dividirse en dos métodos separados ??? ¿Cómo crees que esto solucionó el problema de tu pantalla en blanco cuando es el mismo código? – casillic

+0

Tuve la misma experiencia. Obtuve un PDF en blanco del primer código. Dividirlo en dos como lo hizo Alex, lo hizo funcionar. No puedo explicar por qué. –

10

Si alguien está interesado, aquí está Swift 2.1 código:

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) 
     } 
    } 
+0

Su declaración de guardia significa que no se llama a UIGraphicsEndPDFContext(). ¿Quizás agregue un diferimiento antes? –

+0

@DavidH gracias, David, ¡buena idea! Además, creo que es una buena idea agregar un bloque de finalización tipo 'finalización: (éxito: Bool) ->()' para casos de devolución de guardia –

+1

Ayer publiqué una sesión de preguntas y respuestas sobre cómo producir una imagen de alta resolución al mostrarla en una imagen grande, luego dibujar la imagen en un PDF interesado: http://stackoverflow.com/a/35442187/1633251 –

11

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) 
    } 
} 
+0

esto creando PDF para firstPage! ¿Qué hay de scrollview? –

+0

¡Gran pregunta! Sin embargo, no soy de los que pregunto. Quizás comenzar otra pregunta? – retrovius

+0

Tengo el mismo problema que @SaurabhPrajapati y creé una [Pregunta] (https://stackoverflow.com/questions/47605767/create-a-pdf-file-out-of-an-uiscrollview-in-swift) –

1

Esto va a generar PDF desde UIView y diálogo de impresión abierta, objetivo C. Adjunte - (IBAction)PrintPDF:(id)sender a su botón en la pantalla. Añadir #import <QuartzCore/QuartzCore.h> marco

H Archivo

@interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate> 

    { 
    UIPrintInteractionController *printController; 
    } 

- (IBAction)PrintPDF:(id)sender; 

M Archivo

-(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]; 

    } 

}