Blending Cocoa and Unix: Printing



I've written before about how powerful I find the Mac's Unix foundation, and how much of it I integrate into my programs. More recently I've replaced some of the Unix integration of my applications with functionality accessed via the Cocoa frameworks. With the changes I'm making to my cocoaprint Tcl/Tk library, I'm now blending the Unix and Cocoa (and Carbon) approaches in new ways.

When they rejected one of my apps recently, the App Store reviewers said that one of the major issues is that the app cannot do print previewing, save as PDF, or save as PostScript. That's correct, and it's by design: I had originally designed the printing code to support sending the data to the printer only. Some initial research suggested that it wasn't possible to handle "print preview" or support PDF/PostScript with the particular printing functions I utilized, since I was not using an NSView to prepare the print data.

(Technical aside: the standard Cocoa way of printing is to draw data that is represented in the window on the screen (inside an NSView display) into a printing graphics context, which is then output at the printer. My approach makes use of a more traditional Unix approach, which is to write data to a PostScript or PDF file using Unix command-line tools, and then send that file to the printer.)

After doing some further research, I found that I could add the required functionality to the cocoaprint library: I was able to implement print preview and exporting to PDF and PostScript. However, I did so mostly by using Unix methods, rather than traditional Cocoa printing methods.

For instance: to implement print preview, rather than writing the print data to some temporary file that is then viewed in a Cocoa window or in Preview, I simply open the existing PDF file in the default PDF viewing application (using NSWorkspace methods). To implement exporting as PDF, I simply copy the existing print file to a new location defined by the user (using NSFileManager methods). And to export to PostScript, I use the Unix command-line tool "cupsfilter" (installed on OS X as part of its Common Unix Printing System, or CUPS) to convert the PDF print file to PostScript in a user-defined location.

While these functions are all called under the hood using Unix or file-system methods, they are driven from the native Cocoa print dialog (NSPrintPanel). Many aspects of the print job, including determining the target location of the print output (printer, file or preview) are also managed by Core Printing functions (Core Printing is part of the Carbon framework that has not been deprecated by Apple).

I'm glad I continue to rely on the Unix tools even as I increasingly make use of Cocoa (and Carbon) API calls in my work; the availability of all three in my toolbox gives me more and more flexibility in determining how I approach a programming task, and increases the range of possibilities available to me.

[/general] permanent link

Rejection as positive feedback



On paper, it wasn't a good week for my App Store submissions. Both NameFind and QuickWho were rejected; NameFind was an update, while QuickWho was a new submission.

Initially, this was frustrating: NameFind was rejected for a bug that I couldn't reproduce, and QuickWho had a long list of issues. I had to query the App Store team for more information about the NameFind bug, and the worst of the QuickWho issues was going to require adding some significant functionality to one of my Tk-Cocoa extensions.

Still, a few days later, I'm feeling quite good about the process and bullish on the App Store. Here's why:

I got some helpful suggestions from Apple staffers in the Apple developer forums with some additional things to investigate on the NameFind bugs.

After some further back-and-forth in the user forums, an Apple employee actually called me to follow up, and offered still further suggestions on NameFind.