2011-09-22 5 views
3

Je suis en train de créer un PDF à partir d'une UIView qui peut contenir des images, des étiquettes, etc. J'ai vérifié la référence (GeneratingPDF) et je suis également au courant de la méthode renderInContext:, qui peut être utilisé pour dessiner le contenu de UIView sur le contexte PDF. J'ai utilisé renderInContext: pour créer un PDF. Cependant, les images et le texte ont perdu leur fidélité. c'est-à-dire que les images n'étaient pas sélectionnables individuellement, le texte n'a pas pu être sélectionné/copié, etc. dans le fichier PDF résultant. Il était aussi bon/mauvais que le PDF créé à partir d'un instantané de la UIView.iOS: Créer un fichier PDF UIView

Ma question est, dois-je dessiner les textes & images individuellement pour obtenir ce que je veux (en utilisant CGContextShowTextAtPoint & CGContextDrawImage)? Si oui, alors comment procéder pour numériser le UIView pour les images &? Supposons que je reçois le UIView de l'extérieur & ne suis pas au courant de son contenu.

Répondre

1

Vous devez en effet dessiner les textes/images individuellement dans un CGContextRef (regarder CGPDFContextCreateWithURL) en utilisant des fonctions comme CGContextShowTextAtPoint. Alors que vous pourriez théoriquement scanner votre UIView pour les images/étiquettes, il serait préférable de dessiner la mise en page à partir de zéro. Vous devez avoir un moyen de savoir quels éléments devraient être dans l'UIView. Bien que le code soit très différent, logiquement vous devriez l'aborder de la même manière que si vous deviez dessiner UIView par programme au lieu de le charger depuis une plume.

Si vous voulez vraiment analyser votre UIView, vous pourriez faire quelque chose comme ceci:

for(UIView *subview in parentView.subviews) { 
if([subview isKindOfClass:[UIImageView class]]) { 
    ... 
} else if([subview isKindOfClass:[UITextView class]]) { 
    ... 
} else if([subview isKindOfClass:[UILabel class]]) { 
    ... 
} 
} 
+0

Merci Michael! Donc, êtes-vous sûr que 'renderInContext:' ne peut pas être utilisé dans ce cas? Je pense à des scénarios dans lesquels le 'UIView' a un arrière-plan multicolore ou quelque chose qui pourrait être difficile à dessiner. – Akshay

+0

Oui, j'en suis sûr. J'ai effectivement rencontré ce problème il n'y a pas très longtemps et ma logique a commencé exactement là où vous avez fait (renderInContext :) et j'ai essayé de chercher du code pour dessiner un UIView dans un PDF et à la fin la seule façon de le faire est de utilisez les méthodes CGContext et allez à partir de zéro en dessinant tout dans un CGContextRef. –

+0

Merci encore Michael!Alors, comment dessinez-vous si UIView a un fond avec un dégradé? En outre, mon cas d'utilisation actuel est de créer un PDF à partir d'un UIWebView que j'utilise pour afficher un fichier (par exemple ppt ou doc), pour lequel j'ai trouvé que le texte et les images ne sont pas sous-vues (pas UILabels ou UITextViews). Avez-vous essayé cela aussi? Désolé de ne pas l'avoir spécifié à l'origine. – Akshay

2

J'ai eu une quantité modérée de chance de marcher juste ma hiérarchie de la vue, et appeler -drawRect: moi-même. Il y a un peu mis en place que vous avez faire avant chaque, comme la traduction du ctm et de compensation de la matrice de texte, mais quand vous avez fait cela pour chaque vue, vous pouvez le faire:

UIGraphicsPushContext(ctx); 
[self drawRect:self.frame]; 
UIGraphicsPopContext(); 

Le PDF il génère est basé sur un vecteur - pas seulement un bitmap plat, donc il évolue bien et vous pouvez sélectionner le texte dans un visualiseur/navigateur. Cela ne fonctionne que sur le dessin personnalisé de vanille ordinaire et des trucs très simples comme UILabels. Je doute que cela fonctionnerait avec des objets UIKit plus complexes (je pense aux vues de table et aux vues de défilement). En outre, vous auriez besoin d'un travail supplémentaire pour UIImageViews (que je suppose deviner la propriété de contenu de la couche avec un CGImageRef), et si vous avez d'autres attributs et transformations basés sur la couche - encore plus de travail.

Espérons que Apple nous donnera une meilleure solution que le maintien du code de tirage parallèle!

+0

Cette catégorie UIView a bien fonctionné - je crois qu'elle utilise votre stratégie: https://github.com/mruegenberg/uiview-hierarchical-drawing. Une chose à garder à l'esprit est que si vous utilisez CALayers, vous devrez ajouter du code pour écrire explicitement dans le contexte. Voir cette réponse: http://stackoverflow.com/questions/13783971/maintain-vector-graphics-when-rendering-calayer-into-pdf-output – jeffmax

0

essayer,

{ 
    //read the pdf file 

    CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),  CFSTR("iPhoneAppProgrammingGuide.pdf"), NULL, NULL); 
     PDFfile = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL); 
     CFRelease(pdfURL) 

    CGPDFPageRef page = CGPDFDocumentGetPage(PDFfile,currentpage); 

    context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); 
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); 
    CGContextFillRect(context,self.bounds); 
    CGContextTranslateCTM(context, -1.0, [self bounds].size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 
    CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFArtBox, [self bounds], 0, true)); 
    CGContextDrawPDFPage(context, page);  
    CGContextRestoreGState(context); 
    //CGAffineTransform transform = aspectFit(CGPDFPageGetBoxRect(page, kCGPDFMediaBox), 
               CGContextGetClipBoundingBox(context)); 

     // CGContextConcatCTM(context, transform); 
     UIGraphicsBeginImageContext(CGSizeMake(self.bounds.size.width, self.bounds.size.height)); 


}