This is the first PDF class I have made for the iOS using code from Apple's samples. There could easily be stuff here wrong that I am missing.
I intend this to get images out of for a layer, for example:
image.contents = (id)[self.test imageForPage: 3 size: CGSizeMake(4*dpc, 2*dpc)].CGImage;
Here is this hopefully decent code. Any suggestions are welcome.
@interface PDFDocument : NSObject {
CGPDFDocumentRef pdfFile;
}
- (id) initWithURL: (NSURL*) url;
- (UIImage*) imageForPage: (size_t) pageno size: (CGSize) size;
- (CGSize) sizeOfPage: (size_t) pageno;
@end
@implementation PDFDocument
- (id) initWithURL: (NSURL*) url {
if ([super init])
{
// Open PDF
CGPDFDocumentRef doc = CGPDFDocumentCreateWithURL((CFURLRef)url);
if (doc == NULL)
@throw @"PDF File does not exist.";
pdfFile = doc;
}
return self;
}
- (UIImage*) imageForPage: (size_t) pageno size: (CGSize) size {
if (pdfFile) {
// Get First Page
CGPDFPageRef page = CGPDFDocumentGetPage(pdfFile, pageno);
if (page == NULL)
@throw @"Page does not exist.";
// Get Page Size
CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
// Start Drawing Context to Render PDF
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGRect u = { {0, 0}, size};
CGContextFillRect(context, u);
CGContextSetAllowsAntialiasing(context, NO);
CGContextSaveGState(context);
// Scale PDF
CGContextScaleCTM(context, size.width / cropBox.size.width, size.height / cropBox.size.height);
// Flip Context to render PDF correctly
CGContextTranslateCTM(context, 0.0, cropBox.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); // must retain?
UIGraphicsEndImageContext();
return img;
}
return nil;
}
- (CGSize) sizeOfPage: (size_t) pageno {
if (pdfFile) {
CGPDFPageRef page = CGPDFDocumentGetPage(pdfFile, pageno);
if (page == NULL)
@throw @"Page does not exist";
CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
return cropBox.size;
}
@throw @"No document loaded.";
}
@end
-
1\$\begingroup\$ I have encountered PDF files where the text is written in landscape but the page width and height will tell you that the page is in portrait. When opened in a PDF viewer, the file will be in landscape. I had to add special handling for files like those. Unfortunately, I don't have my code with me right now so I can't share, but I believe you're missing that part. \$\endgroup\$Altealice– Altealice2011年05月31日 05:35:34 +00:00Commented May 31, 2011 at 5:35
-
1\$\begingroup\$ Something like this? ipdfdev.com/2011/03/23/… \$\endgroup\$Jeffrey Drake– Jeffrey Drake2011年05月31日 13:35:01 +00:00Commented May 31, 2011 at 13:35
-
\$\begingroup\$ Yeah, something like that. But I remember mine to be much simpler, like ~8 additional lines only. \$\endgroup\$Altealice– Altealice2011年06月01日 13:29:40 +00:00Commented Jun 1, 2011 at 13:29
1 Answer 1
One immediate change I'd make is how you're handling errors. While try-catch
blocks are extremely common in other programming languages, I actually don't see them all that very often in Objective-C.
That doesn't mean we won't have errors. It just means error handling is typically handled differently in my experience with Objective-C. Just take a look at some of the Foundation methods as example:
stringWithContentsOfFile:encoding:error:
You can send nil
as the argument for the error
, but otherwise, you send the method an NSError
object, and when the method returns, if there was an error, you can check the object to find out what it was. In the case of an init
method, if an error occurred, you'd also want to return nil
as well as loading the error description in the passed error object.
For completeness, it seems like it might be a good idea to create a corresponding PDFPage
class. And instead of imageForPage:size:
being called over and over to create pages, the end user would create instances of PDFPage
. The PDFDocument
in turn isn't much more than an array of PDFPages
with some logic for adding a single page, array of pages, remove pages, from front, back, specific index, etc.
-
\$\begingroup\$ I never liked that kind of error control, although now I would never use exceptions like that either. \$\endgroup\$Jeffrey Drake– Jeffrey Drake2014年02月21日 06:55:05 +00:00Commented Feb 21, 2014 at 6:55