iOS Tips: Viewing PDFs in less than 30 seconds
By using the Quick Look Framework
If you need in your app to present a document like a PDF, a bunch of images, or even a Microsoft Office or iWork document, you can use the Quick Look Framework that ships with iOS.
You start by importing the QuickLook
framework into your project file. You then create a QLPreviewController
, create a QLPreviewControllerDataSource
, hand in as many QLPreviewItem
instances to the data source as you need, and then present the controller. The only wrinkle here is that the QLPreviewItem
and QLPreviewControllerDataSource
objects are just protocols, you have to create concrete types in order to use them.
Before we start the clock, create a new single view application in Xcode, and have a PDF document to hand that you would like to open. In this app we’re going open a PDF from the application bundle, but note that this approach works just was well with a loose file or an internet based URL. With your project and PDF resource in place, we’re ready to start the clock:
- In Xcode, in ViewController.m, below the first
#import
statement, add the following import statement:
@import QuickLook;
- Below the
@import QuickLook;
declaration, add the following code to create aQLPreviewItem
implementation:
/*
* Quicklook Preview Item
*/
@interface PreviewItem : NSObject <QLPreviewItem>
@property(readonly, nullable, nonatomic) NSURL *previewItemURL;
@property(readonly, nullable, nonatomic) NSString *previewItemTitle;
@end@implementation PreviewItem- (instancetype)initPreviewURL:(NSURL *)docURL
WithTitle:(NSString *)title {
self = [super init];
if (self) {
_previewItemURL = [docURL copy];
_previewItemTitle = [title copy];
}
return self;
}@end
/***/
This QLPreviewItem
implementation provides the mandatory previewItemURL
property, but also includes the optional previewItemTitle
property, with a convenience init method to set those properties.
- Next, below the
PreviewItem
implementation add the following code that implements theQLPreviewControllerDataSource
protocol:
/*
* QuickLook Datasource for rending PDF docs
*/
@interface PDFDataSource : NSObject <QLPreviewControllerDataSource>
@property (strong, nonatomic) PreviewItem *item;
@end@implementation PDFDataSource
- (instancetype)initWithPreviewItem:(PreviewItem *)item {
self = [super init];
if (self) {
_item = item;
}
return self;
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
return 1;
}
- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
return self.item;
}@end
/***/
Only two methods are defined in the QLPreviewControllerDaraSource
protocol, the remaining implementation provides storage for the PreviewItem
instance, plus a convenience init method to create the data source.
- Inside the interface declaration for the
ViewController
, add the following property declaration:
@property (strong, nonatomic) PDFDataSource *pdfDatasource;
You’ll need to retain an instance of the QLPreviewControllerDataSource
for when you present the QLPreviewController
.
- Below the
viewDidLoad
method, add the following code, adjusting the name of the file to one that you wish to load from within the application bundle, mine is called article.pdf:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
/*
* get the path to the pdf resource.
*/
NSString *path =
[[NSBundle mainBundle] pathForResource:@"article"
ofType:@"pdf"];
NSURL *docURL = [NSURL fileURLWithPath:path];
/*
* create the Quicklook controller.
*/
QLPreviewController *qlController =
[[QLPreviewController alloc] init];
PreviewItem *item =
[[PreviewItem alloc] initPreviewURL:docURL
WithTitle:@"Article"];
self.pdfDatasource =
[[PDFDataSource alloc] initWithPreviewItem:item];
qlController.dataSource = self.pdfDatasource;
/*
* present the document.
*/
[self presentViewController:qlController
animated:YES completion:nil];
}
With this code you get the path to the target file from the main bundle, create a NSURL
pointing to the file; you then create a QLPreviewController
, a new PreviewItem
using the URL with the title "Article". Next you create a new data source, handing it the preview item, and then finally, present the QuickLook controller.
- Stop the clock!
I have created a sample project that you can use if you want to see this approach in action.