Opening a PDF in Swift
It’s easy to overlook some of our most basic developer actions, because we do them so frequently. However, with the continuous development and increase in the popularity of Swift, we want to revisit a fundamental function that’s important to us and hopefully to you, too: opening a PDF.
Here’s how it’s done (you can find all of the project’s files on GitHub):
Step 1 — Creating the Project
Xcode - File → New → Project…, choose “Single View Application”:
Enter the product and organization names and choose Swift as the language:
Choose the destination and create the project.
Step 2 — Adding a PDF to the Project
Drag and drop a document into the newly created project. Choose to add it to your app’s target:
The document will show up in the file list on the left and in the “Copy Bundle Resources” build phase of your app’s target:
Step 3 — Adding Buttons that Present PDFs
We’re going to create our layout in code, so the first thing we do is getting rid of the storyboard file. To complete the removal we also have to reset the main interface:
Then, we can set up our window and root view controller in AppDelegate.swift
:
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { // Initialize the window. var window: UIWindow? = { let window = UIWindow(frame: UIScreen.mainScreen().bounds) window.backgroundColor = .whiteColor() return window }() func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Set up the root view controller. let viewController = ViewController() viewController.title = "PDF Viewer" let navigationController = UINavigationController(rootViewController: viewController) window?.rootViewController = navigationController window?.makeKeyAndVisible() return true } }
Next, add two buttons to ViewController.swift
:
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // To keep things DRY we're going to define our button attributes in an array // and loop over it to create our buttons. let buttonAttributes = [(title: "Open Document in Web View", selector: #selector(openDocumentInWebView(_:)), yOffset: CGFloat(-100)), (title: "Open Document in PSPDFKit", selector: #selector(openDocumentInPSPDFKit(_:)), yOffset: CGFloat(100))] for buttonAttribute in buttonAttributes { let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle(buttonAttribute.title, forState: .Normal) button.setTitleColor(.blueColor(), forState: .Normal) button.sizeToFit() button.addTarget(self, action: buttonAttribute.selector, forControlEvents: .TouchUpInside) view.addSubview(button) // We're using a bit of Auto Layout to keep our buttons centered. NSLayoutConstraint(item: button, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0).active = true NSLayoutConstraint(item: button, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: buttonAttribute.yOffset).active = true } } // We'll implement these button actions later. @objc private func openDocumentInWebView(sender: UIButton) { } @objc private func openDocumentInPSPDFKit(sender: UIButton) { } }
Be sure to mark the button actions @objc
to make the private
methods callable from Objective-C.
Step 4 — Opening a PDF Inside of a Web View
Xcode - File → New → File…, choose “Swift File”:
Name the file WebViewController
.
Inside of the new file, we’re creating a new class WebViewController
that contains a web view:
import UIKit class WebViewController: UIViewController { // We're going to show a PDF with the help of this web view. let webView = UIWebView() override func viewDidLoad() { super.viewDidLoad() // Make sure the web view is shown fullscreen. webView.frame = view.frame view.addSubview(webView) } }
Next, we can implement openDocumentInWebView
in ViewController.swift
:
@objc private func openDocumentInWebView(sender: UIButton) { // Get URL of PDF document. guard let documentURL = NSBundle.mainBundle().resourceURL?.URLByAppendingPathComponent("Document.pdf") else { return } let urlRequest = NSURLRequest(URL: documentURL) // Create web view controller. let webViewController = WebViewController() webViewController.webView.loadRequest(urlRequest) let navigationController = UINavigationController(rootViewController: webViewController) // Add a close button that dismisses the web view controller. webViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .Plain, target: self, action: #selector(dismissController(_:))) // Present the document. presentViewController(navigationController, animated: true, completion: nil) } @objc private func dismissController(sender: UIBarButtonItem) { dismissViewControllerAnimated(true, completion: nil) }
After only these few steps we’re able to tap on the button and scroll through a PDF document, but nothing else. No zooming, no annotations, only the one scrolling view mode and no other functionality.
Here’s where PSPDFKit comes in.
Opening a PDF with PSPDFKit
You can download a demo version of PSPDFKit by going to pspdfkit.com and clicking on the “Try Now” button.
All you have to do is drag & drop PSPDFKit.framework
from the .dmg you just downloaded into the “Embedded Binaries” section of your app’s target:
PSPDFKit.framework
will also show up in “Linked Frameworks and Libraries”.
Take a look at our documentation to get more information about integrating PSPDFKit.
We start using PSPDFKit by importing the module and implementing openDocumentInPSPDFKit
in ViewController.swift
:
// First we need to import the PSPDFKit module. import PSPDFKit @objc private func openDocumentInPSPDFKit(sender: UIButton) { // Get URL of PDF document. guard let documentURL = NSBundle.mainBundle().resourceURL?.URLByAppendingPathComponent("Document.pdf") else { return } // Create PSPDFDocument and PSPDFViewController. let document = PSPDFDocument(URL: documentURL) let pdfController = PSPDFViewController(document: document) // Present document. let navigationController = UINavigationController(rootViewController: pdfController) presentViewController(navigationController, animated: true, completion: nil) }
Now we can view PDF documents in PSPDFKit. But not only that: We can zoom, create annotations, take a look at the document’s outline and lots of other things. All this with just these few lines of code. If we want to customize our PDF viewer further, we just need to pass) a PSPDFConfiguration
object to PSPDFViewController
.
Notice how we didn’t even need to implement a close button. Why? Because PSPDFKit automatically detects that PSPDFViewController
is presented modally and adds the close button to the navigation bar. Our main goal is to help developers with their jobs, and one of the ways we help them is by creating less things to implement.
Finished Implementation
When we put it all together, here’s what the final ViewController.swift
implementation will look like:
import UIKit import PSPDFKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // To keep things DRY we're going to define our button attributes in an array // and loop over it to create our buttons. let buttonAttributes = [(title: "Open Document in Web View", selector: #selector(openDocumentInWebView(_:)), yOffset: CGFloat(-100)), (title: "Open Document in PSPDFKit", selector: #selector(openDocumentInPSPDFKit(_:)), yOffset: CGFloat(100))] for buttonAttribute in buttonAttributes { let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle(buttonAttribute.title, forState: .Normal) button.setTitleColor(.blueColor(), forState: .Normal) button.sizeToFit() button.addTarget(self, action: buttonAttribute.selector, forControlEvents: .TouchUpInside) view.addSubview(button) // We're using a bit of Auto Layout to keep our buttons centered. NSLayoutConstraint(item: button, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0).active = true NSLayoutConstraint(item: button, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: buttonAttribute.yOffset).active = true } } @objc private func openDocumentInWebView(sender: UIButton) { // Get URL of PDF document. guard let documentURL = NSBundle.mainBundle().resourceURL?.URLByAppendingPathComponent("Document.pdf") else { return } let urlRequest = NSURLRequest(URL: documentURL) // Create web view controller. let webViewController = WebViewController() webViewController.webView.loadRequest(urlRequest) // Present the document. let navigationController = UINavigationController(rootViewController: webViewController) webViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .Plain, target: self, action: #selector(dismissController(_:))) presentViewController(navigationController, animated: true, completion: nil) } @objc private func openDocumentInPSPDFKit(sender: UIButton) { // Get URL of PDF document. guard let documentURL = NSBundle.mainBundle().resourceURL?.URLByAppendingPathComponent("Document.pdf") else { return } // Create PSPDFDocument and PSPDFViewController. let document = PSPDFDocument(URL: documentURL) let pdfController = PSPDFViewController(document: document) // Present document. let navigationController = UINavigationController(rootViewController: pdfController) presentViewController(navigationController, animated: true, completion: nil) } @objc private func dismissController(sender: UIBarButtonItem) { dismissViewControllerAnimated(true, completion: nil) } }