可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
There are a lot of resources about how to display a PDF in an App\'s UIView
. What I am working on now is to create a PDF from UIViews
.
For example, I have a UIView
, with subviews like Textviews, UILabels
, UIImages
, so how can I convert a big UIView
as a whole including all its subviews and subsubviews to a PDF?
I have checked Apple\'s iOS reference. However, it only talks about writing pieces of text/image to a PDF file.
The problem I am facing is that the content I want to write to a file as PDF is a lot. If I write them to the PDF piece by piece, it is going to be huge work to do.
That\'s why I am looking for a way to write UIViews
to PDFs or even bitmaps.
I have tried the source code I copied from other Q/A within Stack Overflow. But it only gives me a blank PDF with the UIView
bounds size.
-(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);
}
Please help. Thanks.
回答1:
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
回答2:
Additionally, if anyone is interested, here is the Swift 3 code:
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)
}
}
回答3:
If someone is interested, here\'s Swift 2.1 code:
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)
}
}
回答4:
This will generate PDF from UIView and open print dialog, objective C.
Attach - (IBAction)PrintPDF:(id)sender
to your button on screen.
Add #import <QuartzCore/QuartzCore.h>
framework
H File
@interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate>
{
UIPrintInteractionController *printController;
}
- (IBAction)PrintPDF:(id)sender;
M File
-(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];
}
}
回答5:
I don\'t know why, but casilic\'s answer gives me blank screen on iOS6.1. The code below works.
-(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;
}