Il existe de nombreuses ressources sur la manière d'afficher un PDF dans la variable UIView
d'une application. Je travaille actuellement sur la création d'un PDF à partir de UIViews
.
Par exemple, j'ai une UIView
, avec des sous-vues telles que Textviews, UILabels
, UIImages
, comment puis-je convertir une bigUIView
dans son ensemble, y compris toutes ses sous-vues et sous-vues en PDF?
J'ai vérifié référence iOS d'Apple . Cependant, il ne parle que d'écrire des morceaux de texte/image dans un fichier PDF.
Le problème auquel je suis confronté est que le contenu que je veux écrire dans un fichier en tant que PDF est énorme. Si je les écris pièce par pièce dans le document PDF, le travail à effectuer sera considérable… C'est pourquoi je cherche un moyen d'écrire UIViews
dans des fichiers PDF ou même des images bitmap.
J'ai essayé le code source que j'ai copié à partir d'autres questions/réponses dans Stack Overflow. Mais cela ne me donne qu'un PDF vide avec la taille des bornes 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);
}
S'il vous plaît aider. Merci.
Notez que la méthode suivante crée juste un bitmap de la vue; il ne crée pas de typographie réelle.
(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);
}
Assurez-vous également que vous importez: QuartzCore/QuartzCore.h
De plus, si cela vous intéresse, voici le code 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)
}
}
Si quelqu'un est intéressé, voici le code 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)
}
}
Ceci générera PDF à partir d’UIView et ouvrira une boîte de dialogue d’impression, Objective C . Attachez - (IBAction)PrintPDF:(id)sender
à votre bouton à l’écran . Ajouter #import <QuartzCore/QuartzCore.h>
framework
Fichier H
@interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate>
{
UIPrintInteractionController *printController;
}
- (IBAction)PrintPDF:(id)sender;
Fichier 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];
}
}
Avec Swift 4.2, vous pouvez combiner la méthode CALayer
' render(in:)
avec la méthode UIGraphicsPDFRenderer
' s writePDF(to:withActions:)
afin de créer un fichier PDF à partir d'une instance UIView
.
L'exemple de code suivant Playground montre comment utiliser render(in:)
et writePDF(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)")
}
Remarque: pour utiliser playgroundSharedDataDirectory
dans votre Playground, vous devez d’abord créer un dossier appelé "Données de la Playground partagée" dans votre dossier "Documents" macOS.
L'implémentation complète de la sous-classe UIViewController
ci-dessous montre un moyen possible de reformuler l'exemple précédent pour une application 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)")
}
}
}
Un moyen très simple de créer un PDF à partir d'UIView consiste à utiliser l'extension UIView.
Swift 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édit: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/