Reading & Displaying PDF Documents

Working with raw PDF documents can be a time consuming and frustrating task. This tutorial will teach you how to use the VFR Library to quickly access, display, and browse PDF documents within your own applications!

Introduction

There are many scenarios where it may become necessary to display a PDF in an iOS App. In doing so, there can be many complications in getting PDFs to render correctly. There are also additional features such as printing, e-mailing, viewing bookmarks, handling rotation, and more that should be accounted for. While many of these features may not be complicated to include, some can be very tricky to get working correctly.

PDF Viewer Final Product

Step 1: Install The VFR Library

For this app, we'll start out by creating a new Xcode project as a "Single-View Application". Also, we'll be using ARC, so make sure that "Use Automatic Reference Counting" is checked.

New Project

Required Frameworks

Our PDF "Reader" library requires a few additional frameworks to be added to our project: QuartzCore, ImageIO, and MessageUI.

If you're already familiar with adding frameworks to a project, then you can skip this next part and get right into "Adding the Library to Our Project".

Otherwise, to add those frameworks, click on your Project from the Project Navigator. Choose your target, then find the "Build Phases" tab at the top. Underneath "Build Phases", expand the "Link Binary With Libraries" section and then click the "+" button in the lower left-hand corner.

Required Frameworks

Now, add the required frameworks (QuartzCore, ImageIO, MessageUI).

Add Required Frameworks

Your "Link Binary With Options" section should now look like this:

Required Frameworks Have Been Added

Adding the Library to Our Project

Our PDF "Reader" library can be downloaded from GitHub here: https://github.com/vfr/Reader. We can now drag our "Reader" library into our project and we're almost ready to start. I've created a new Group in my project called "PDF Reader" where I'm adding the library (you only need to include the "Sources" and "Graphics" directories).

Add the 'Reader' Library

Unfortunately, at this point, "Reader" is not ARC-ready. So, we'll have to do some refactoring. There are three (3) files that we'll need to manually update before we can tell Xcode to refactor for ARC: "ReaderDocument.m", "ReaderContentPage.m", and "ReaderThumbFetch.m" (for reference, you can find basic instructions for these files here: http://www.vfr.org/2012/05/reader-arc-conversion/.)

Basically, what we're going to do is edit each of these files to use plain __bridge casts, like so:

ReaderDocument.m:

Change

... = [NSString stringWithString:(id)theString];

to
...

= [NSString stringWithString:(__bridge id)theString];

ReaderContentPage.m:

Change

... = CGPDFDocumentCreateX((CFURLRef)fileURL, phrase);

to...

... = CGPDFDocumentCreateX((__bridge CFURLRef)fileURL, phrase);

ReaderThumbFetch.m:

Change


... = CGImageSourceCreateWithURL((CFURLRef)thumbURL,

to...

... = CGImageSourceCreateWithURL((__bridge CFURLRef)thumbURL, NULL);

With the above changes made, go to Edit > Refactor > Convert to Objective-C ARC...

Refactor for ARC

You will be prompted to "Select Targets to Convert." Make sure that your current target is selected, then press "Check".

Check Target for Refactoring

The prompt will guide you through the process, you should be able to just hit "Next" without issue.

Refactor 'Next' Step

Then you'll be able to "Review Changes", and you can select "Save".

Refactor 'Save'

Finally, we need to include our "Reader" library header into our main ViewController.h and set our main view controller as a ReaderViewControllerDelegate:

#import "ReaderViewController.h"

@interface MTViewController : UIViewController <ReaderViewControllerDelegate>

Step 2: Setup

The complicated part of our project setup is over. From this point, it's quick work to start viewing PDFs in our apps -complete with printing, bookmarks, thumbnails, email, and more!

First thing, let's add a demo PDF to our project. Once again, I've created a new group, this one I've called "PDFs".

I've then added a PDF named "typo_tips.pdf" that I downloaded from fontshop.com in the "resources directory" that you can use (direct link). Of course, feel free to try any PDF that you already have as well.

Add Our PDF

To open our PDF, we'll add a single UIButton in our main ViewController.xib.

Add Our UIButton

We'll then hook up our UIButton to a method that we'll call didClickOpenPDF.

Assign Our UIButton To Its Method

The rest of the work will be handled within this "didClickOpenPDF" method in our main ViewController.m.

First, we'll grab our PDF document from our app bundle.

Next, we'll create a "ReaderDocument" that our "Reader" will be able to view. Notice that, if our document were password protected, we could set the password as the final parameter.

Next, we make sure that our "ReaderDocument" was successfully created, before implementing our "ReaderViewController" which will handle the rest of the PDF operations for us.

And between the braces in the "document" check, we'll load our "ReaderViewController" object.

In this example, we'll be presenting our "ReaderViewController" as a modal view, although we could alternatively present it with a UINavigationController if our app were using a UINavigationController. We have various options for the style of presentation and transition that we could use for our ModalViewController, so I'd encourage you to experiment with the styles that work best for your app. In this case, we'll try to imitate the native Apple PDF style from iBooks.

Add the following lines after "readerViewController.delegate = self;".

Lastly, we need to actually present our ModalViewController:

As you can see, once we've included our "Reader" library, it's relatively simple to view and interact with PDFs in our iOS apps. Here's the entire method that we used:

If you run and build our application now, you'll see the many features already working for your PDF viewer.


Final Product

There's just one final thing we need to handle: dismissing our PDF Reader ViewController when the user presses the "Done" button.

This is handled with a simple, straightforward method:

Step 3: Options

As mentioned earlier, the "Reader" library supports many of these functions beyond just showing PDFs, such as printing, bookmarks, etc. By default, most of these features are enabled. You can, however, choose to set these each as best suits your application by editing the "ReaderConstants.h" file. Each of these features is listed on the "Reader" GitHub page, which I'll show here:

  • READER_BOOKMARKS - If TRUE, enables page bookmark support.
  • READER_ENABLE_MAIL - If TRUE, an email button is added to the toolbar
    (if the device is properly configured for email support).
  • READER_ENABLE_PRINT - If TRUE, a print button is added to the toolbar
    (if printing is supported and available on the device).
  • READER_ENABLE_THUMBS - If TRUE, a thumbs button is added to the toolbar
    (enabling page thumbnail document navigation).
  • READER_DISABLE_IDLE - If TRUE, the iOS idle timer is disabled while
    viewing a document (beware of battery drain).
  • READER_SHOW_SHADOWS - If TRUE, a shadow is shown around each page
    and the page content is inset by a couple of extra points.
  • READER_STANDALONE - If FALSE, a "Done" button is added to the toolbar
    and the -dismissReaderViewController: delegate method is messaged when
    it is tapped.
  • READER_DISABLE_RETINA - If TRUE, sets the CATiledLayer contentScale
    to 1.0f. This effectively disables retina support and results in
    non-retina device rendering speeds on retina display devices at
    the loss of retina display quality.

Next Time: Writing PDF Documents

Now you've seen how easy it can be to view PDFs in iOS. In the next tutorial in this series, we'll look at some of the ways to create our own PDFs within our Apps.

Tags:

Comments

Related Articles