Wednesday, July 06, 2011

Crossword Forge QuickLook Plugin

While at WWDC there was a lab helping people develop QuickLook plugins. I had often felt that Crossword Forge would really benefit from this plugin. Users would be able to simply press the spacebar and get a look at their puzzle. I attended the lab and got started on my plugin. A relatively short time later I had a plugin that would display the title and puzzle grid. It took into account styling of the title, backdrop pictures, right to left languages, puzzle masks and a lot of other small but important details of the file format. It wasn't 100% complete but it was complete enough to work on the next step. I needed to make sure it worked in the real world. Up to now I had been running the plugin directly in Xcode using the command line tool "qlmanage". I needed it to run, just like a user expects, when I pressed the space bar in the finder on any .cwz document.
It turns out there are 3 ways (at least) to install a QuickLook plugin. I could install it in /System/Library/QuickLook/, ~/Library/QuickLook/, or I could install it directly in my app itself in the subdirectory /Contents/Library/QuickLook/. For me the last option was the best since Crossword Forge did not have a separate installer, I didn't need to worry about adding the plugin to the above mentioned directories. I didn't have to worry about authentication, and it also meant that the end user wouldn't be asked to install it (another option but a tech support nightmare).
With the plugin installed, in my app, I figured it would just work, unfortunately it did not. It turns out I was missing 2 very important steps. First I had to update my info.plist file in 2 places. I had to add a LSItemContentTypes item to my CFBundleDocumentTypes. This has to match the plugins value for this. In my case it equals com.solrobots.crosswordforge.cwz. I also had to add a separate entry for UTExportedTypeDeclarations in my info.plist. (One gotcha here is in relation to the UTTypeTagSpecification, Apple's docs say to use the com.apple.ostype tag but Apple's own Garage Band has a hyphen in that same key. Its written as com.apple.os-type . I'm not certain which is correct, but I'm going with the hyphen version for now, which seems to work).
After all of this, it still wasn't working. I had all the pieces in place, I just had to debug it.
My first check was to make sure that QuickLook manager knew about my plugin. I called "qlmanage -m plugins" and sure enough my new plugin was loaded into the system. Next I tried to find out what the system thought was the file type. I used the tool "mdls" for this. Unfortunately it was not assigning the right UTI to my file. I checked and re-checked my info.plist, restarted the finder, restarted the system, nothing seemed to work. Finally I found "lsregister -dump" (you'll have to specify the full path to this tool), which gave me a few clues. Launch Services was getting the UTI but it was a duplicate entry and it wasn't trusted. I needed a way to update the Launch Services database. The easiest way to do this is to change the applications mod date "touch appName.app", and then duplicate one of my .cwz files in the Finder. One more thing: before you change the mod date of your app, don't forget to put it in your Applications Folder. It won't update properly unless it's there.