Migrating from Apple PDFKit

Apple's PDFKit provides a great starting point for integrating PDF support into your iOS app. It is a system library and as such the easiest to integrate.

PSPDFKit, on the other hand, is a cross-platform PDF framework with more advanced features, fine-grained control over various aspects of PDF handling and a lot of customization options, including:

  • Advanced and native UI & UX with support for most PDF features
  • Support for all annotations defined in the PDF specification
  • Import & export of annotations in JSON and XFDF formats
  • Accessing files embedded in documents
  • Adding watermarks to documents
  • Programmatic form filling
  • Indexed full-text search (near-instant search results)
  • Loading of documents from custom sources, with on-the-fly decryption
  • Advanced, customizable rendering including CMYK color space support
  • Custom bookmarks implementation (bookmarks are not part of the PDF spec)
  • Available on multiple platforms with great interoperability
  • Constantly improving with new features
  • First class support directly from our engineers

To simplify migrating a code base from PDFKit to PSPDFKit as much as possible, we provide a wrapper called PDFXKit. It is a drop-in replacement with little or no changes required allowing you to program against the PDFKit API while using PSPDFKit under the hood. See Section Easy Transition with PDFXKit for more info.

Introduction

The PSPDFKit API can be overwhelming at first, especially when coming from Apple PDFKit. But once you get through the basic concepts, it becomes straight forward. We've traded a bit of simplicity for flexibility and performance. We achieve this by using a couple of techniques and patterns.

For example, the responsibility for providing, parsing, and managing various PDF objects and concepts is split into individual classes. Those are called accordingly: PSPDF...Provider, PSPDF...Parser, PSPDF...Manager. We expose those classes publicly in order to give you hooks for customization as well as advanced control and performance optimization.

Overview

The only UI classes provided by Apple's PDFKit is the PDFView and the PDFThumbnailView. All remaining classes in Apple's PDFKit is what Apple calls "utility classes". Let's take a look at those and how they relate to PSPDFKit.

The following table shows an overview of Apple's PDFKit classes that have a roughly corresponding class in PSPDFKit:

Apple's PDFKit PSPDFKit
PDFView PSPDFViewController
PDFThumbnailView PSPDFScrubberBar
PDFDocument PSPDFDocument
PDFAnnotation PSPDFAnnotation
PDFOutline PSPDFOutlineElement

The PDFPage class doesn't have a corresponding class in PSPDFKit, the concept of a "page" is supported mainly via page indexes as described in more detail in section Page Handling.

The PDFSelection class doesn't have a corresponding class in PSPDFKit. While PDFSelection is very generic in Apple's PDFKit, covering multiple use-cases, PSPDFKit offers more dedicated objects for each use case. Text selected by a user is a UI concept. For more info, see Section Text Handling.

Document Handling

The PDFDocument class in Apple PDFKit represents a single PDF document either stored on disk as a file or loaded via an NSData object. This class corresponds to PSPDFDocument in PSPDFKit.

A PSPDFDocument consists of one or more PSPDFDocumentProvider's. You can think of one provider corresponding to a single file on disk. This allows you to treat multiple PDF files as a single document in cases where you need it. Many customers use this feature to split up large documents into individual files, say to download each part individually on demand.

Page Handling

As noted above, PSPDFKit doesn't have a corresponding class for PDFPage. Anything related to a page is accessed via the document or a related object by passing a page index. For example, you use PSPDFDocuments annotationsForPageAtIndex:type: to get annotations for a specific page. Page indexed access allows PSPDFKit to better optimize for performance.

The main object to manipulate pages of a document is the PSPDFDocumentEditor and related classes (see announcement blog post. It allows you to:

  • Add pages
  • Remove pages
  • Duplicate pages
  • Rotate pages
  • Extracting pages (saving as a new PDF document)

Please consult the Document Editing guide, Section Programmatic Access.

Text Handing

Other than selecting text at the UI level, extracting text and inspecting blocks of text are probably the two main use cases of PDFSelection in Apple PDFKit.

In PSPDFKit, both of these use cases are covered by PSPDFTextParser, which you can access via the textParserForPageAtIndex: method of PSPDFDocument. It offers a simple API to get the text, glyphs (PSPDFGlyph), words (PSPDFWord), textBlocks (PSPDFTextBlock) and even images (PSPDFImageInfo).

In a PDF, text usually corresponds to glyphs positioned at an absolute location on a specific page. PSPDFKit uses advanced heuristics to group these glyphs into meaningful words and text blocks.

Outline

The PDFOutline class encapsulates the outline concept of a PDF document. PSPDFKit has a corresponding class named PSPDFOutlineElement which works similarly to PDFOutline. You can access the outline via the outline property on PSPDFDocument:

1
2
let document = /* Create a PSPDFDocument  */
let rootOutlineElement = document.outline
1
2
PSPDFDocument *document = /* Create a PSPDFDocument  */;
PSPDFOutlineElement* rootOutlineElement = document.outline;

Having the root outline element, you can walk the outline tree, get info, and perform operations on the outline elements, similar to how you would do it with PDFOutline. For more info, please consult the API reference.

Annotations

Apple PDFKit provides a single PDFAnnotation class together with a small PDFBorder utility class representing annotations and their borders. PSPDFKit supports all annotations as defined by the PDF specification with a very rich and flexible API. We have an extensive guide covering all aspects of annotations: Annotations Guide .

Search

PSPDFKit offers two search options:

  • Regular search: equivalent to Apple PDFKit, easy to use
  • Indexed full-text search: blazing fast, requires more set-up

To perform a regular search for a document, create an instance of PSPDFTextSearch, passing in the loaded PSPDFDocument via its initializer. Searching can be triggered via calling searchForString:, which will start a search in a background queue. Implement PSPDFTextSearchDelegate on the receiving object and set the text search object's delegate to your object to be notified of search result updates.

To learn more about our blazingly fast indexed full-text search, please take a look at the Indexed Full-Text Search guide.

Rendering

Apple PDFKit allows you to render a PDFPage into a specific context using the drawWithBox:toContext: method. Similarly, the easiest way to render a page with PSPDFKit is to use one of the following PSPDFDocument methods:

Copy
1
2
3
// PSPDFDocument
func imageForPage(at pageIndex: UInt, size: CGSize, clippedTo clipRect: CGRect, annotations: [PSPDFAnnotation]?, options: [PSPDFRenderOption : Any]? = nil) throws -> UIImage
func renderPage(at pageIndex: UInt, context: CGContext, size: CGSize, clippedTo clipRect: CGRect, annotations: [PSPDFAnnotation]?, options: [PSPDFRenderOption : Any]? = nil) throws
Copy
1
2
3
// PSPDFDocument
- (nullable UIImage *)imageForPageAtIndex:(NSUInteger)pageIndex size:(CGSize)size clippedToRect:(CGRect)clipRect annotations:(nullable NSArray<PSPDFAnnotation *> *)annotations options:(nullable NSDictionary<PSPDFRenderOption, id> *)options error:(NSError **)error;
- (BOOL)renderPageAtIndex:(NSUInteger)pageIndex context:(CGContextRef)context size:(CGSize)size clippedToRect:(CGRect)clipRect annotations:(nullable NSArray<PSPDFAnnotation *> *)annotations options:(nullable NSDictionary<PSPDFRenderOption, id> *)options error:(NSError **)error;

Beyond this basic rendering support, PSPDFKit offers an advanced, asynchronous rendering pipeline allowing you control various aspects of the rendering result and performance. You first create a PSPDFRenderRequest which specifies what and how to render the page. You use that render request to create a PSPDFRenderTask, set yourself as a delegate on that and schedule it in a PSPDFRenderQueue. Once finished, the render task will notify the delegate and pass it the resulting image. See the Rendering and Caching article for more detail.s

For more info on advanced rendering, please consult the API reference for those classes as well as our PSPDFCatalog example project. See the example projects article for more details.

Basic User Interface

As of iOS 11, PDFKit provides two UI classes for displaying and browsing PDF files — PDFView and PDFThumbnailView.

PDFView is the main UI class allowing you to display a PDF document using different display modes and options to tweak the appearance. The corresponding class in PSPDFKit is the PSPDFViewController.

PDFThumbnailView is an accessory control for a PDFView showing a strip of thumbnails for each page of the currently displayed PDF document. The corresponding class in PSPDFKit is the PSPDFScrubberBar.

Unlike PDFView, the PSPDFViewController is meant to be a drop-in solution with very little code or UI required from your side. All you have to do is create a PSPDFViewController and present it as-is. Everything else is handled for you automatically by default — including displaying the PSPDFScrubberBar.

The following code snippet demonstrates how to display a PDF using PSPDFViewController and a thumbnail bar matching the one from PDFKit:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import PSPDFKit

// Load the document.
let documentURL = Bundle.main.url(forResource: "Document", withExtension: "pdf")!
let document = PSPDFDocument(url: documentURL)

// Create a configuration object and tweak the thumbnail bar which will use
// the appropriate view, in this case the `PSPDFScrubberBar`.
let configuration = PSPDFConfiguration { builder in
    builder.thumbnailBarMode = .scrubberBar
    // Add your configuration options here.
}

// Put the PDF view controller inside a navigation controller in order to
// give it a navigation bar for various PDF-related controls.
let pdfViewController = PSPDFViewController(document: document, configuration: configuration)
let navigationController = UINavigationController(rootViewController: pdfViewController)

present(navigationController, animated: true)
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import <PSPDFKit/PSPDFKit.h>

// Load the document.
NSURL *documentURL = [NSBundle.mainBundle URLForResource:@"Document" withExtension:@"pdf"];
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a configuration object and tweak the thumbnail bar which will use
// the appropriate view, in this case the `PSPDFScrubberBar`.
PSPDFConfiguration *configuration = [PSPDFConfiguration configurationWithBuilder:^(PSPDFConfigurationBuilder *builder) {
    builder.thumbnailBarMode = PSPDFThumbnailBarModeScrollable;
    // Add your configuration options here.
}];

// Put the PDF view controller inside a navigation controller in order to
// give it a navigation bar for various PDF-related controls.
PSPDFViewController *pdfViewController = [[PSPDFViewController alloc] initWithDocument:document configuration:configuration];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:pdfViewController];

[self presentViewController:navigationController animated:YES completion:NULL];

The result should look something like this:

PDF page coordinates

Advanced User Interface

Apart from basic support for displaying and browsing PDFs with the two PDFKit classes above, everything else needs to be implemented from scratch with PDFKit. PSPDFKit on the other hand provides everything you need to handle PDFs in your app, ready to be used out of the box.

When presented within a navigation controller, the PSPDFViewController puts a couple of buttons into the navigation bar by default, giving you access to the following features:

Adding, deleting, and editing annotations. The first button in the navigation bar is by default the annotations button giving you access to the annotation toolbar. Support of annotations is a big part of PSPDFKit, please consult our Annotations feature page as well as our Annotations guide for an in-depth look.

Searching & navigating search results. Next to the annotations button you'll find the loupe button, which presents the PSPDFSearchViewController.

Displaying & managing the document outline, its annotations, bookmarks, and files. Next up is the bookmark button which gives you access to the PSPDFOutlineViewController, PSPDFBookmarkViewController, PSPDFAnnotationTableViewController, PSPDFEmbeddedFilesViewController. See our Core Viewer feature page for a visual walk-through of these features.

Inserting, deleting, and reordering pages. The last button in the navigation bar gives you access to the PSPDFThumbnailViewController from which you get to the PSPDFDocumentEditorViewController allowing you to manage the pages of a document. See our Document Editor feature page and the corresponding Document Editing guide for more info.

PSPDFKit offers more UI components not directly accessible via the PSPDFViewController including the PSPDFDocumentPickerController and the PSPDFTabbedViewController. All of these components are designed to be easy to integrate and customize in order to perfectly blend into your app. To learn more, please take a look at our Customizing the Interface guide as well as our extensive documentation and API reference.

Easy Transition with PDFXKit

If your app is already using PDFKit, migrating the full code base to PSPDFKit can be a major undertaking and a deal breaker for many developers. In this case, we encourage you to give our PDFXKit a try.

PDFXKit is a drop-in replacement giving you the same API as PDFKit while using PSPDFKit under the hood — only a few tweaks required. PDFXKit gives you full access to the underlying PSPDFKit allowing you take take advantage of all PSPDFKit features, components, and tools if and when you need them.

PDFXKit is open source, please visit the project page on GutHub for more info.

Conclusion

Having experience with Apple PDFKit, by now you should have a rough idea on how to translate that to PSPDFKit. If you have an existing codebase using PDFKit, our PDFXKit makes the transition to PSPDFKit a breeze.

While PDFKit is a great starting point to add basic PDF support to your app, PSPDFKit goes much further offering you a cross-platform drop-in solution with many additional UI components, advanced PDF features, and first class support directly from the developers.

Please consult our website, our guides, and our API reference for further info about various parts of PSPDFKit.