How to build iPhone Apps that use PDFHummus
Good night.
So you want to have your iPhone app create a report in PDF. Well, you got to the right place :)
Creating PDFs with the PDFHummus library carries the benefit of being faster and with a smaller memory signature than other PDF creation solutions, so using it for iPhone is ideal. The same would go for parsing PDFs.
Making PDFHummus available as a library for iOS is no different than doing it for any other C or C++ library. Essentially, you have to compile it for the iPhone and iPhone simulator targets on xCode (as well as iPad if you care to), and generate a universal library that you can later use with the app project itself. PDFHummus also requires doing this for the accompanying libraries – LibJpeg, LibTiff and Freetype. no need to do anything special for ZLIB as the OSX and iOS both make ZLIB available as a system dylib.
In this post i’ll provide explanation on how to prepare the various libraries and how to code PDFHummus in the app itself. Some tips on how to use PDF in iPhone will also be provided. And of course we got some sample materials.
The example app code and project can be downloaded from here (the binaries included are compiled on my macbook air) – App project download
You can download the libraries (PDFWriter,LibJpeg…) Xcode projects and source files from here – PDFWriter and referenced libs
To run the code, just compile the Xcode projects of the libs (all targets…), set the references to the result libs (static) from the sample code, and it should work. complaints and praises, send them over here – gal@pdfhummus.com
Finally, you can download the app from the itunes store with this link
Let’s go.
Sort out the libraries
To be able to include PDFHummus in your app, you first need to compile PDFWriter and the referenced libs for iPhone (freetype, libjpg, libtiff).
This requires adding a target to any existing project for a cocoa library with iPhone as the building architecture. You also want a target for the iPhone simulator.
Then combine the targets to a universal library with a 3rd aggregator target.
This site here
has a good tutorial on how to do that for each of the libraries.
b.t.w you could do the same with gcc and the libraries supplied makefiles, but it’s too complicated to bother with IMO. Xcode projects is an easier path.
I used the instructions to build Xcode projects that can create the desired universal libraries. you can find them with the download for this post.
you’ll probably have to fix the references to source code, but other than that it should be fine.
Using the Library with the app
Once you have all the libraries set up, start your app project, and add the libraries to be linked against.
The next step is to add the code to create (or parse) PDF files in the app itself.
The example provided is a simple automatic solver for Sudoku Puzzles. It uses the library to build a PDF describing the solved board, which can be sent as an attachment by email.
The main class dealing with PDF Creation is SudokuBoardPDFCreator. I’m using a pair of .h and .mm files to define it.
The h. file contain its interface definition. there’s a single function that accepts a board and path and creates a PDF file there. Its definitions is like this:
@class SudokuBoard;
@interface SudokuBoardPDFCreator : NSObject
-(BOOL)createPDFForBoard:(SudokuBoard*)inBoard atFilePath:(NSString*)inFilePath;
@endYap. Got some objective-c code here, that’s inevitable with iOS…but not too bad. A single method returning boolean value for success/fail, and accepting a SudokuBoard (essentially a 9X9 matrix of 1-9 values, with 0 as empty indication) and the path to place the file in.
Now for the implementation. The implementation is written in a file with the extension .mm. the reason i’m using .mm and not .m is because there’s C++ here, and for the objective-c compiler to know C++ keywords (namespace, class etc.) one must use .mm.
The implementation itself creates a grid of 9X9 and then writes the board numbers in each of the cells. Most of the code is the same as it would have been for OSX or PC, the parts that we’ll review have to do with what’s special for iOS.
Opening the PDF file for writing
So, we begin with how the PDF file is opened:
PDFWriter pdfWriter; status = pdfWriter.StartPDF([inFilePath UTF8String],ePDFVersion13);
The code creates an instance of PDFWriter and then just calls StartPDF as it would have with a regular OSX application. The only exception is that it’s using the objective C notation to get the UTF 8 char* string from the NSString object passed to it, like this:
[inFilePath UTF8String]
Luckily all this works out of the box with PDFHummus using UTF8 as the string implementation. The good thing is that the regular fopen/fclose/fread C operators work so we can use the regular file implementation of PDFHummus, and don’t have to write our own stream implementation special for iOS. If you do want to use customer streams, that’s possible too with StartPDFWithStream that accepts an IByteWriterWithPosition stream object.
A note about what path to provide. In iOS files are stored in special locations that are tied to an app. This way an app just don’t get to put files in unsafe locations. you can see which path i provided to the PDF by checking out the call to createPDFForBoard:atFilePath: as it is done in SudokuViewController class:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *file = [[documentPaths objectAtIndex:0]
stringByAppendingPathComponent:@"Sudoku.pdf"];
…
[pdfCreator createPDFForBoard:_dataController.board atFilePath:file];I’m using the documents folder path for the app by calling NSSearchPathForDirectoriesInDomains, and then placing there a file named Sudoku.pdf in the first (and hopefully only) folder there (which is the documents folder).
Using a font (or other resources)
Next comes drawing the grid, which is no special, and then writing the numbers. For writing the numbers i’m using courier. for PDFHummus to work with it i needed a file. not looking for too much trouble i simply included courier in the application bundle and used it from the code.
To put courier in the application bundle do this:
go to the Xcode project.
open the “supporting files” group (where the plist file is). put the font file there.
select the project in the project explorer, and then the app target from the main editor area.
choose the “build phases” tab and open the “Copy Bundle Resources”.
drag the font file from the “supporting files” group to the “Copy Bundle Resources” area.
This will take care of copying the font file to the application bundle resources area. This can work also with images that you would like to use.
Using the font in code now is very simple. All that you have to do is to grab the file path for the font. You can see how to do this if you look further at the SudokuBoardPDFCreator createPDFBoard implementation:
NSString *fontPath = [[NSBundle mainBundle]
pathForResource:@"Courier New"
ofType:@"ttf"];
PDFUsedFont* font = pdfWriter.GetFontForFile(
[fontPath UTF8String]);Simple :) from the static mainBundle object grab the path for the “Courier new.ttf” file with pathForResource and you are done.
Now, getting the utf8 char* path is the same as what we did earlier – [fontPath UTF8String].
That’s it. Anything else is just the same as creating PDF on your OSX or PC.
What can i do with this PDF now?
Now that you got yourself a nice PDF, how to send it? How to use it with the rest of the apps on my iPhone (like Acrobat reader, pPreview or the Bookshelf). Worry not, i’ll explain that too.
To send a PDF as email attachment, use the following code (in SudokuViewController):
if([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *mail=[[MFMailComposeViewController alloc]init];
mail.mailComposeDelegate=self;
[mail setSubject:@"Look at my nice Sudoku Board!"];
NSData * pdfData = [NSData dataWithContentsOfFile:inPDFFilePath];
[mail addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"Sudoku.pdf"];
NSString * body = @"";
[mail setMessageBody:body isHTML:NO];
[self presentViewController:mail animated:YES completion:nil];
}We’re using the MFMailComposeViewController to create a new mail, set the subject, add the PDF file as attachment and later display the email for further edit and sending. The important part is how to use the PDF file, let’s look at the specific part:
NSData * pdfData = [NSData dataWithContentsOfFile:inPDFFilePath]; [mail addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"Sudoku.pdf"];
We’re just loading the PDF file into an NSData object, using dataWithContentsOfFile. Later just add the NSData object as an attachment with the right mime types, using addAttachmentData of the MFMailComposeViewController object. (To complete an implementation of this you should also implement MFMailComposeViewControllerDelegate with your view controller. Check the code for this, it’s not PDF particular).
You can also open this PDF file with any application that supports opening PDF. To do that use the UIDocumentInteractionController class. It simply receives a file, and then can be used to open any file that is registered to open this file type. So pretty. Here’s the code:
NSURL* fileURL = [[NSURL alloc] initFileURLWithPath:inPDFFilePath]; interactionController = [UIDocumentInteractionController interactionControllerWithURL: fileURL]; interactionController.delegate = self; [interactionController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES];
The code simply creates a UIDocumentInteractionController for the file using interactionControllerWithURL method of UIDocumentInteractionController. later it opens the matching window for this controller by calling its presentOptionsMenuFromRect:inView:animated method.
Simple. And that’s all there is to it. We’re done :)
Summary
We reviewed how to use the PDFHummus library in the context of IOS app. The required steps are:
Compile PDFHummus and accompanying libraries as universal libraries for the iPhone, iPhone simulator (and any other IOS targets that you wish to have).
Add the universal libs to your app.
Write the PDf reading/writing code as you would have done it for a regular OSX or PC application, with taking care of the following:
files are placed in special locations in IOS. find the right place to create the PDF file in using the specialised system functions.
resources are taken from the application bundle, as they would have of an OSX application, so grab them using the specialised system functions.
Use the PDF file as attachment, or open in another application with the IOS classes of
MFMailComposeViewControllerDelegateandUIDocumentInteractionController
You can find all the materials i used for this example here:
The app project and code – https://www.box.com/s/epoo4b3stt9ystdmep8b
The PDFHummus Xcode, accompanying libraries projects and sources – https://www.box.com/s/a4rn00zs7wdcexq2kxus .
(you can also get the PDFHummus code/projects from the github project by downloading the current snapshot…i’ll release this projects/sources on the next regular release) – https://github.com/galkahana/PDF-Writer.
Thanks for reading,
XOXO,
Gal

