I wanted an NSBrowser with checkboxes for Arq to replace its ugly file-selection mechanism. Some type of file tree with checkboxes UI (like Dropbox and Crashplan use) seemed like a good fit, and I prefer NSBrowser to a (potentially gigantic) NSOutlineView. But I was stumped as to how to get checkboxes in an NSBrowser.

Searching the net gave me some clues, like I should subclass the cell that the NSBrowser uses and call [NSBrowser setCellClass:], but searching also led me down some fruitless paths. Contrary to what you may have read, don’t subclass NSBrowserCell — it’s unsubclassable.

Finally I stumbled on Apple’s ComplexBrowser sample code. It uses a subclass of NSTextFieldCell. And it gives some clues on how to capture the checkbox click.

The Code

When I began my search, I was hoping to find someone’s sample project that did just what I wanted, but no luck. So I’m publishing my sample project for the next person who goes looking for such a thing:

https://github.com/sreitshamer/FSBrowser

Enjoy!

- Stefan

 

As part of my process for releasing a new version of Arq, I needed a way for my script to get the version of an app bundle.

So, I wrote a simple utility called appversion which prints the value for the CFBundleVersion key in an app’s Info.plist.

For example:

	appversion /Applications/iPhoto.app

yields:

	8.1

Download the 32/64-bit Universal binary (in a zip file) here:

appversion.zip

 

Unlike web apps, desktop apps crash without the app’s developer knowing about it, unless the user sends a crash report to the developer. Whenever an app crashes, OS X puts up a dialog for the user to submit a crash report to Apple. Unfortunately for non-Apple apps that crash report never gets to the developer!

So, Arq needs its own “crash reporter”. After reading Daniel Jalkut’s nice roundup of crash reporters, I chose Breakpad because it seems the most similar to Apple’s built-in crash reporter.

Adding Breakpad to your Mac OS X app is easy since the Breakpad team created a Framework around it.

Building Breakpad

Just download the source, open the XCode project under src/client/mac and compile the target “All”.

If you’re on 10.6 though, you’ll need to set the compiler for all the targets and sub-projects to “GCC 4.0″, or else you’ll get an error “GCC 4.2 is not compatible with the Mac OS X 10.4 SDK”.

The default settings for the project (at least as of svn revision 394) create a “32-bit Universal” build. 64-bit isn’t supported yet. See the Breakpad issues list for more details.

Adding Breakpad to Your App

Once you’ve built Breakpad, drag Breakpad.framework into the Linked Frameworks folder of your XCode project. Be sure to check the “copy items into the destination group’s folder” box in the sheet that appears. Also check the target you want to add Breakpad to.

Next, create a “Copy Files” build phase in your target with a destination of “Frameworks”, and drag Breakpad.framework into that.

Next, add a bunch of variables to your app’s Info.plist, including:

	BreakpadProduct
	BreakpadProductDisplay
	BreakpadVersion
	BreakpadVendor
	BreakpadURL
	BreakpadRequestComments

See the comments in Breakpad.h for how to set those variables. One tricky bit: BreakpadRequestComments should be a <string> with a value of "TRUE" in your Info.plist, not a <true>.

As an example, here’s how I set my plist variables for Arq:

    <key>BreakpadProduct</key>
    <string>Arq</string>
    <key>BreakpadProductDisplay</key>
    <string>Arq</string>
    <key>BreakpadVersion</key>
    <string>1.1</string>
    <key>BreakpadVendor</key>
    <string>Haystack Software</string>
    <key>BreakpadURL</key>
    <string>http://crashreport.<yourserverhere>.com/arq/new</string>
    <key>BreakpadReportInterval</key>
    <string>0</string>
    <key>BreakpadLogFiles</key>
    <array>
        <string>/var/log/system.log</string>
    </array>
    <key>BreakpadLogFileTailSize</key>
    <string>40000</string>

Finally, create a Breakpad object in your app:

    BreakpadRef bp = BreakpadCreate([[NSBundle mainBundle] infoDictionary]);
    if (bp == NULL) {
        NSLog(@"failed to create Breakpad");
    }

That’s it! Now crash your app to try it out :)

On the server side, you’ll need something to process the report. I’ll post my server-side code soon. Tweet me @reitshamer if you need it right now.

UPDATE: I put the server-side code at http://github.com/sreitshamer/breakpadserver.

© 2012 Philomathy Suffusion theme by Sayontan Sinha