A few days ago I tweeted about my frustrations with document signings apps.
My frustrations boiled down to 3 main points:.
- Lengthy unskippable onboarding
- Forced signup
- Questionable privacy policies
So I wanted to build a completely free, zero-bloat, no catch document signer. And after sitting down for 10 minutes, it was done. So instead of going through the hassle of trying to publish it, I’m gonna write this tutorial so if you want it, you can make it.
Step One
Open Xcode, make a new project, and this is important, pick a ‘Document app’

Give it a nice name, I chose PleasantPDF. Make sure the Interface is Storyboard, the Life Cycle is UIKit App Delegate, and the Language is Swift.

Support PDFs
Now we need to tell iPadOS/iOS that our app can handle PDFs. So go to
Info > Document Types
and we’ll replace the existing entry. Give it the name ‘PDF’, and the Types
com.adobe.pdf
Add CFBundleTypeRole
to ‘Additional document type properties and give it the value Editor.

Open PDFs in app
So the key to make this app so quickly and so simply is to not try and write a PDF Viewer, hook it into PencilKit or touches or anything, we’re going to use QuickLook.
Open DocumentBrowserViewController.swift
Jump down to the function func presentDocument(at documentURL: URL)
and delete the contents of the function, we’re going to replace this implementation.
But first, create a new class level variable called documentUrl: URL?
.
Now in the presentDocument(at:)
function, fill it with this:
func presentDocument(at documentURL: URL) {
self.documentUrl = documentURL
self.documentUrl?.startAccessingSecurityScopedResource()
let qlController = QLPreviewController()
qlController.dataSource = self
self.present(qlController, animated: true, completion: nil)
}
You’ll get an error saying that
Cannot assign value of type 'DocumentBrowserViewController' to type 'QLPreviewControllerDataSource?'
So go ahead and click Fix on that issue, or if it doesn’t appear, just add QLPreviewControllerDataSource
to inheritance of the class.
class DocumentBrowserViewController: UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate, QLPreviewControllerDataSource {
Implement the function numberOfPreviewItems
like this:
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
1
}
And now the magic bit, this function
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return self.documentUrl! as QLPreviewItem
}
Build & Run!
Wrapping Up
That’s literally it. The Document app template type handles adding to the Share Sheet, and you can build upon this however you like. But this will get you a very quick and no-frills document signer.
Warning: Don’t try and use this app to redact documents, this is not secure.