David Gelphman's Blog

1 Comment

Adding Save PDF to iBooks Support to Your Application

As I wrote recently, the ability to create a PDF document from an application’s printed content is one of my favorite features that Apple added in iOS 9. This feature leverages the printing system so that if your application can print, a user will also be able to use the new “Save PDF to iBooks” feature. Well, almost.

The key is that your application needs to offer printing by using Apple’s “Share Sheet”, instead of using the older method of using a UIPrintInteractionController. And unfortunately, as of my writing this, all of Apple’s sample code demonstrating how to implement printing in an iOS application uses the UIPrintInteractionController method of presenting printing to the user.

I ran into this recently when I emailed the developers of one of my favorite iOS applications and suggested they add support for the “Save PDF to iBooks” to their app. After all, the app already supported the Share Sheet for a number of tasks other than printing but it supported printing using the old UIPrintInteractionController. The developer was kind enough to reply to my suggestion with interest, but the response I got was: “I’d like to but I don’t know how to do that.”

Poking around Apple’s developer site, I found the handy page AirPrint for Developers. It includes a link to the 2014 WWDC session on AirPrint (there was none in 2015) which is a great presentation with tons of info for app developers getting started with printing on iOS. And the AirPrint for Developers page has four links to sample code that implement printing in various ways. Unfortunately none of these samples implement the Share Sheet method of printing.

So I grabbed one of Apple’s samples and updated it. I started with one that I myself wrote (long ago) at Apple. It demonstrates how to print content from a WebView in both a basic way and also by using some fancier techniques to add more control to the layout of content on the printed pages. Updating it to use the Share Sheet is pretty straightforward.

The only substantive change needed to make the sample app use the share sheet is to take out the use of the UIPrintInteractionController from the sample and replaced it with the use of a UIActivityViewController. This controller takes an array of “Activity Items” as part of its initialization. When the controller is presented it determines what activities (or actions) can be taken on those activity items and allows the user to choose from those actions.

The UIActivityViewController determines that printing is a supported activity if the activity items array contains both an object of the UIPrintInfo class and also a source of print data. The source of print data can be a printing item or items (e.g. a photo or photos), a UIPrintFormatter object, or a UIPrintPageRenderer subclass. For the original sample code, the source of print data was a UIPrintPageRenderer subclass that the code created and assigned to the myRenderer local variable. For fun in the new code I also added an NSURL corresponding to the URL of the web page the user is visiting. This allows the Share Sheet to show more actions for the sample app than just those associated with printing. Once the UIActivityViewController is created, all that is needed is to present it and UIKit does the rest. I mostly stole the code to present the activity view controller from this sample.

Here’s the updated code snippet that replaces the old usage of the UIActivityViewController in the original sample: 

NSURL *url = [NSURL URLWithString:[self.urlField text]];
NSArray *activityItemsArray = 
  [NSArray arrayWithObjects: myRenderer, printInfo, url, nil];
UIActivityViewController *activityViewController =
  [[UIActivityViewController alloc]

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  //iPad, present the view controller inside a popover
    self.activityPopover =
      [[UIPopoverController alloc]
  if (![self.activityPopover isPopoverVisible]) {
    //Dismiss if the button is tapped while pop over is visible
    [self.activityPopover dismissPopoverAnimated:YES];
 //iPhone, present activity view controller as is
 [self presentViewController:activityViewController animated:NO completion:nil];

Running the modified app on an iPad and touching the action icon brings up the Share Sheet instead of the Printing UI directly (as it would have if I’d not modified the original sample). From there you can see that both the Print icon as well as the “Save PDF to iBooks” icon appears on the Share Sheet. And both behave as expected! 

Operation Mincemeat

If you’ve already got printing working in your app, now’s the time to update to using the Share Sheet method instead of the older method. Without a lot of extra work on your part, users get a great new option to save your application’s content in a print ready format. And if you’ve not added printing to your application to date, the “Save PDF to iBooks” feature provides yet another reason to do so.


1 Comment

Save PDF to iBooks

New in iOS 9 is the ability to save web pages as a PDF document to iBooks. It is a feature that is near and dear to my heart, in part because it is the last major feature I worked on at Apple before I left in early 2013.

What users of iOS 9 may notice is that Safari offers a new item in the Share Sheet: “Save PDF to iBooks”. They may think of this as a Safari specific feature.

iOS 9 Share Sheet


But the Photos app also allows this, as will every iOS app that presents printing using the iOS “Share Sheet” (in iOS programming parlance, using an ActivityViewController). If an app can print via the Share Sheet then “Save PDF to iBooks” automatically appears as well.

During my career at Apple I worked primarily on the printing subsystems of Mac OS X and iOS. Much of that work was on the software plumbing needed for users to print on paper. But a portion of that work was enabling the ability to produce a PDF file corresponding to what otherwise would have been printed output. Save as PDF from the print dialog was part of OS X since version 10.0 shipped in 2001.

When creating the printing system for iOS, allowing for the ability to create a PDF reproduction of the results of printing was a goal of the design from the beginning. To me it seemed almost more important to allow users to capture content to store on their device to take with them (or email or whatever) than it was to produce pieces of paper. The design of the printing system allowed for it but the user facing feature was left out. So in the summer of 2012 I worked on an early implementation of what is now shipping. And I’m thrilled that it’s now out.

Executives at Apple talk about the desire to “surprise and delight our users”. Well I experienced that firsthand when I got a notification from Apple’s “Tips” app on my iPhone soon after updating to iOS 9. For me the (ironic) surprise was that the tips app was telling me about a feature that I worked on. And I was delighted to see that it was finally shipping. 

Save PDF to iBooks Tip

1 Comment

On the Debug Podcast

Recently I made an appearance on the Debug podcast, hosted by Guy English and Rene Ritchie. It was terrific fun talking with them and we’ve gotten a lot of positive feedback from listeners. We had so much to talk about that they broke it up into two parts.

In Part 1 we talk about how I got into computing, working with FORTH at Stanford Linear Accelerator Center, my days at Adobe Systems in the late 1980s, working at General Magic, and then RBI Software Systems. Part 1 ends just as we are talking about RBI moving to Apple to work in the Graphics and Imaging Group in June, 2000.

Part 2 begins as I arrive at Apple and begin working on Printing and Graphics just as Mac OS X was ramping up for a beta release in the fall of 2000 and the 10.0 release in the Spring of 2001. It was a fantastic time to start at Apple and be a part of its evolution. And yes, we also talk about bagels.

If you haven’t already, I hope you listen in.


AWK! That Can’t Be Right!?

Predicting when software will be ready to ship is hard. Especially when the software involved is:

  • a complete rewrite from scratch of already existing software.
  • being written by a completely different team (and company) than the one that wrote the original code.
  • a system software component that interacts with virtually every 3rd party app on the platform.
  • required to be fully compatible with the existing software, plus new software and hardware in development.

But that was exactly the scenario I was in, along with Rich Blanchard and the rest of the development team, when I was at Adobe Systems circa 1991 writing a replacement for Apple’s LaserWriter printer driver. And the software we were writing was a critical part of Adobe’s strategic plan for preserving its largest income source at the time, PostScript licensing revenue. No surprise that there was a lot of scrutiny about the project and when it was going to be completed.

Years later, the website MacJournals.com did a write up about the project, including quite a bit about what role the LaserWriter driver software played in the printing system on Mac OS at the time. I have my minor quibbles with some of the details of that write up but one thing was true: that software project really burned me to the ground and was a major factor in my deciding to leave Adobe for greener pastures in 1993.

The Definition of Bad Management

There are a lot of stories about the project I could tell that would raise the hair of every software engineer on the planet, but one clearly defines the term “bad management”.

Part way into the project, Adobe hired “Stoy Aho” to manage the project and the engineering team. As far as I could tell, Stoy had no experience managing a software project or software engineers and there was no evidence that he knew how to write software beyond simple UNIX shell scripts. And even that ability became suspect.

As the completion date for the software kept being pushed out (see the bulleted list above for why), upper level management at Adobe started having meetings every day at 8am to discuss the status of the project. Stoy went to these daily meetings to report how things were going. In order to satisfy his need for something new to report, each team member was required to write a status report each day.

But we were converging on completing the software and some of the tension the engineering team members were feeling began to dissipate; things were looking good. So it was a complete surprise when Stoy came to me and told me how worried Adobe management was about the project. It turned out that he was showing them information he had calculated from our bug tracking database. By using the rate we were fixing bugs and observing the rate that new bugs came in, he had potentially useful information about predicting when the software would be ready to ship.

And that is why he was alarmed. Despite our sense that things were going much better, his analysis of the data indicated that they were getting progressively worse. I asked how he computed the results that he obtained and Stoy said he’d written an AWK script to process the raw bug count data. I immediately demanded that he show me the script.

I didn’t know the AWK programming language but it didn’t take me long to find the problem. At a critical point in his computations, Stoy had inverted the numerator and denominator in one of the calculations, causing his script to produce results that were the exact inverse of the truth! His program showed that the faster we fixed bugs, the longer it would take to ship.

Repeat after me: Stoy’s AWK script showed that the faster we fixed bugs, the longer it would take for the software to be ready.

This occurred over 20 years ago so I don’t remember exactly what I said at the time, but I’m pretty sure my response at the time was something besides AWK.