I've used the following methods to generate a PDF from a UIView. All of them create the PDF but loses quality:
Method 1:
@implementation UIView(PDFWritingAdditions)
- (void)renderInPDFFile:(NSString*)path
{
CGRect mediaBox = self.bounds;
CGContextRef ctx = CGPDFContextCreateWithURL((__bridge_retained CFURLRef)[NSURL fileURLWithPath:path], &mediaBox, NULL);
CGPDFPageRef page;
CGContextDrawPDFPage(ctx, page);
CGPDFContextBeginPage(ctx, NULL);
// Also tried following commented lines but no luck
// CGContextSetFlatness(ctx, 0.1);
// CGContextSetAllowsAntialiasing(ctx, YES);
// CGContextSetAllowsFontSmoothing(ctx, YES);
// CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -mediaBox.size.height);
[self.layer renderInContext:ctx];
CGPDFContextEndPage(ctx);
CFRelease(ctx);
}
@end
Method 2:
- (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);
}
I think I may be missing some settings for the pdf context, not sure. Also I've create png image from UIView with following method which is exact same quality:
- (UIImage *)imageFromView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:@"pdf.png"];
// instructs the mutable data object to write its context to a file on disk
[UIImagePNGRepresentation(img) writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
return img;
}
Can someone see what I'm doing wrong? Thanks.
Is this using a retina display? It could be a contentsScale thing. Have a look at this SO post
EDIT Ok, now that you've posted before & after pics, I see that what you want the invoice UIView to be rendered as nice, high quality, printable vector data in your PDF.
I'm pretty sure that [CALayer renderInContext] always produces raster data, so you're probably better off constructing the PDF manually. And if you're talking about tax invoices, do you really want the layout to change with the next iOS update?
However, you could look at this answer, which reluctantly suggests using the UIView as a template system for your PDF layout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With