<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>carpeaqua by Justin Williams &#187; Development</title>
	<atom:link href="http://carpeaqua.com/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://carpeaqua.com</link>
	<description></description>
	<lastBuildDate>Fri, 25 Jun 2010 12:16:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<cloud domain='carpeaqua.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Getting Started With Core Data, Bindings and NSViewController</title>
		<link>http://carpeaqua.com/2010/03/03/getting-started-with-core-data-bindings-and-nsviewcontroller/</link>
		<comments>http://carpeaqua.com/2010/03/03/getting-started-with-core-data-bindings-and-nsviewcontroller/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 18:54:54 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[bindings]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[coredata]]></category>
		<category><![CDATA[nsviewcontroller]]></category>
		<category><![CDATA[samplecode]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=492</guid>
		<description><![CDATA[If you&#8217;ve been following me on Twitter, you&#8217;ve probably seen me make reference to @secondgear.app 3.0. I am indeed working on a third app to put in the garage, and it is also offering me the opportunity to get acquainted with a lot of technologies I haven&#8217;t exactly used outside of staring at some samples [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve been following me on Twitter, you&#8217;ve probably seen me make reference to <em>@secondgear.app 3.0</em>.  I am indeed working on a third app to put in the garage, and it is also offering me the opportunity to get acquainted with a lot of technologies I haven&#8217;t exactly used outside of staring at some samples before.  Notably:</p>

<ul>
<li>Core Data</li>
<li>Cocoa Bindings</li>
<li><code>NSViewController</code></li>
<li>Unit testing</li>
<li>And more!</li>
</ul>

<p>One of the trends in Mac development in recent years is the prevalence of single window applications such as iPhoto, Aperture and Coda.  Single window interfaces can be less complex in terms of user interaction, but it can also lead to a more complex underpinning if you don&#8217;t watch yourself where you have a single window controller with everything in it<sup>1</sup>.  Apple has aimed to address this with the <code>NSViewController</code> class, which lets you manage portions of the user interface in their own separate class.  If you have done any work on the iPhone it&#8217;s similar to <code>UIViewController</code> in many aspects.</p>

<p>Building your single window app using <code>NSViewController</code> is something any new Cocoa programmer should embrace, but most of the tutorials and walkthroughs I&#8217;ve seen online do not make use of it.  </p>

<p>As a starting point, I picked the <a href="http://cocoadevcentral.com/articles/000085.php">Build A Core Data Application</a> tutorial on CocoaDevCentral.  The article walks you through creating a &#8220;Blogging&#8221; application that stores posts, categories and authors.  The tutorial is a great introduction to Core Data&#8217;s concepts, but it also shoves all of the logic into a single nib and window controller.    This is understandable given it being a tutorial on Core Data rather than general app architecture, but I hit a bit of a stumbling block when trying to wrap my head around how to use my Core Data entities through multiple view controllers.</p>

<p><img src="http://carpeaqua.com/wp-content/uploads/2010/03/masterdetailvc.png" alt="Master Detail VC" class="center" /></p>

<p>I&#8217;ve uploaded a sample project to my <a href="http://github.com/carpeaqua/MasterDetailVC">Github account</a> that should be a good starting point.  Rather than having everything in a single window, I extracted the table view and the post details into their own view controllers.  </p>

<p>The architecture of the application should be fairly straightforward:</p>

<ul>
<li><strong>MDVCAppDelegate</strong>: This has all the Core Data boilerplate code and <code>NSApplicationDelegate</code> methods.  One thing to note is that I am creating default categories and authors in the <code>managedObjectContext</code> method if they don&#8217;t exist.  I picked up that tip from Marcus Zarra&#8217;s <a href="http://www.amazon.com/dp/1934356328/?tag=carpeaqua-20">Core Data book</a>.  I am not really a big fan of having all the Core Data junk stuffed into the AppDelegate, but shifting it off to its own controller can be an exercise for the user.</li>
<li><strong>MDVCMainWindowController</strong>: The main window controller has the base NSArrayController for all the posts.  The nut of this class is in the <code>windowDidLoad</code> method.</li>
</ul>

<pre>
<code>
- (void)windowDidLoad
{
  static NSInteger kSourceListViewIndex = 0;
  static NSInteger kDetailViewIndex = 1;

  self.postsListsViewController = [[MDVCPostsListViewController alloc] initWithArrayController:self.postsArrayController];
  NSView *sourceListSplitViewContentView = [[self.splitView subviews] objectAtIndex:kSourceListViewIndex];
  NSView *sourceListView = [self.postsListsViewController view];
  [sourceListView setFrame:[sourceListSplitViewContentView bounds]];
  [sourceListView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
  [sourceListSplitViewContentView addSubview:sourceListView]; 
  
  // And now let's load the detail view.
  self.postDetailViewController = [[MDVCPostDetailViewController alloc] initWithArrayController:self.postsArrayController];
  NSView *detailSplitViewContentView = [[self.splitView subviews] objectAtIndex:kDetailViewIndex];
  NSView *detailView = [self.postDetailViewController view];
  [detailView setFrame:[detailSplitViewContentView bounds]];
  [detailView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
  [detailSplitViewContentView addSubview:detailView]; 
}
</code></pre>

<p></p>

<p>What I&#8217;m doing is allocating an instance of each view controller and passing it a reference to the window controller&#8217;s array controller to bind against.</p>

<ul>
<li><strong>MDVCPostsListViewController</strong>: If you look in the Xib, you&#8217;ll see that everything is bound through <code>Files Owner.postsArrayController</code>.  This is our reference to the main window controller&#8217;s array controller.  Do take note that the NSTableView has its <code>content</code>, <code>selectionIndexes</code> and <code>sortDescriptors</code> bound.  </li>
<li><strong>MDVCPostDetailViewController</strong>: Like the other view controller, this one binds everything through <code>Files Owner.postsArrayController</code>, but goes through <code>selection</code> rather than <code>arrangedObjects</code> since it displays the details for the currently selected post.  </li>
<li><strong>MDVCCategoriesWindowController</strong>: A window controller that lets you adjust the categories the posts can be associated with.  Nothing too sexy here.</li>
<li><strong>MDVCAuthorsWindowController</strong>: Same as above, but for authors.</li>
</ul>

<p>This is how I do it, but I&#8217;m sure there&#8217;s another (and possibly better way).  One idea that comes to mind is using an NSObjectController in <code>MDVCPostDetailViewController</code> and having it observe the selection property of the parent array controller to manually set the controller&#8217;s content object property when the selection changes.     </p>

<p>I put it up on Github mainly because it makes it a lot easier to update and track the changes.  If you find ways to improve the code, please <a href="http://carpeaqua.com/contact/">let me know</a>.  I am mainly posting all of this for the Google Gods in hopes that someone will someday find this, learn something and have a better application architecture going forward.</p>

<ul>
<li><a href="http://github.com/carpeaqua/MasterDetailVC">MasterDetailVC Sample</a></li>
</ul>

<p><strong>Update</strong>: Martin Pilkington <a href="http://www.mcubedsw.com/blog/index.php/site/comments/building_a_modern_cocoa_app/">has responded</a> with a slightly different approach to the sample app.  He extracts the Core Data implementation out of AppDelegate and into its own set of classes as well as relies more on KVO than abusing NSArrayController through Interface Builder.  His version also uses Rentzsch&#8217;s excellent MOGenerator to generate the Core Data classes.  </p>
<ol class="footnotes"><li id="footnote_0_492" class="footnote">Martin Pilkington wrote a bit about this in his <a href="http://www.mcubedsw.com/blog/index.php/site/comments/size_matters/">Size Matters</a> post</li></ol>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/03/03/getting-started-with-core-data-bindings-and-nsviewcontroller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install Beta Developer Tools In Sparse Disk Images</title>
		<link>http://carpeaqua.com/2010/02/22/install-beta-developer-tools-in-sparse-disk-images/</link>
		<comments>http://carpeaqua.com/2010/02/22/install-beta-developer-tools-in-sparse-disk-images/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 19:40:23 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=457</guid>
		<description><![CDATA[You may have heard that I don&#8217;t do iPhone or iPad development at this time. That said, it&#8217;d be silly to not keep track of what Apple is up to with the platform they care for most. When Apple releases developer beta tools for the mobile platforms, I don&#8217;t install the tools on my main [...]]]></description>
			<content:encoded><![CDATA[<p>You <a href="http://twitter.com/justin/status/9433619283">may</a> <a href="http://twitter.com/kevinhoctor/status/9446230488">have</a> <a href="http://carpeaqua.com/2009/10/16/back-to-the-mac/">heard</a> that I don&#8217;t do iPhone or iPad development at this time.  That said, it&#8217;d be silly to not keep track of what Apple is up to with the platform they care for most.</p>

<p>When Apple releases developer beta tools for the mobile platforms, I don&#8217;t install the tools on my main Mac hard drive.  Instead, I install the tools in a sparse disk image that is completely separate from any other tools.  Does it help?  I&#8217;m not sure since the /Developer folder is self contained as of a few releases ago, but it&#8217;s a practice I continue to do out of habit and safety.</p>

<p>Here&#8217;s how to do it:</p>

<ol>
<li>Open <code>/Applications/Utilities/Disk Utility.app</code></li>
<li><code>File -&gt; New -&gt; Blank Disk Image</code></li>
<li>Set the parameters like so.  </li>
</ol>

<p><img src="http://carpeaqua.com/wp-content/uploads/2010/02/sparse_diskimage.png" alt="Sparse Image In Disk Utility" /></p>

<p>The benefit of using a sparse disk image is that it will grow as necessary rather than allocating and taking up a full 8GB or whatever value you set it to.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/22/install-beta-developer-tools-in-sparse-disk-images/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>So you say Xcode sucks&#8230;</title>
		<link>http://carpeaqua.com/2010/02/22/so-you-say-xcode-sucks/</link>
		<comments>http://carpeaqua.com/2010/02/22/so-you-say-xcode-sucks/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 04:42:40 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=452</guid>
		<description><![CDATA[While at NSConference, I had a chat with Dave Dribin and Jamie Pinkham about why Xcode could be a better IDE. They both asserted that it could be more than it is. Having never used another IDE seriously, I asked both of them what features were missing from Xcode that made other environments like IntelliJ [...]]]></description>
			<content:encoded><![CDATA[<p>While at NSConference, I had a chat with <a href="http://www.dribin.org/dave/blog/">Dave Dribin</a> and <a href="http://jamiepinkham.com/">Jamie Pinkham</a> about why Xcode could be a better IDE.  They both asserted that it could be more than it is.  Having never used another IDE seriously, I asked both of them what features were missing from Xcode that made other environments like IntelliJ and Visual Studio so much better.</p>

<p>A few examples they gave me were:</p>

<ul>
<li>The <a href="http://www.jetbrains.com/resharper/">Resharper refactoring tool</a> for Visual Studio runs circles around Xcode&#8217;s refactoring tools.  I rarely use Xcode&#8217;s tools for more than renaming ivars and methods, so this seems nice.</li>
<li>Syntax checking while you type.  Much like you type a document and get misspelling underlined as you go, other IDEs apparently will tell you when you mistyped an ivar or method name.</li>
<li>Automatic header generation based.</li>
<li>Better autocompletion </li>
<li>You get the point.</li>
</ul>

<p>The ideas they offered were appetizing, but nothing I feel are giant voids in Xcode.  That being said, I&#8217;d love to see Apple improve Xcode into the IDE everyone wants it to be, so I am proposing the following:</p>

<ol>
<li><a href="http://bugreporter.apple.com/">File bugs</a> on each enhancement you want to Xcode.</li>
<li>Post the bug information to <a href="http://openradar.appspot.com/">OpenRadar</a>.</li>
<li>Notify others via a blog post or Twitter so others interested in a similar feature can dupe it.</li>
<li>Pray that the Apple Gods add support.</li>
</ol>

<p>I&#8217;ll star the ball rolling:</p>

<ul>
<li><a href="http://openradar.appspot.com/7223977">Xcode&#8217;s documentation viewer should be a separate application</a></li>
<li><a href="http://openradar.appspot.com/7648205">Xcode should autocomplete calls to &#8220;super&#8221;</a></li>
<li><a href="http://openradar.appspot.com/radar?id=160410">Xcode should auto-import for any class used</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/22/so-you-say-xcode-sucks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serial Numbers Are Dead.  Long Live Serials.</title>
		<link>http://carpeaqua.com/2010/01/25/serial-numbers-are-dead-long-live-serials/</link>
		<comments>http://carpeaqua.com/2010/01/25/serial-numbers-are-dead-long-live-serials/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 19:46:21 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[activation]]></category>
		<category><![CDATA[registration]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=415</guid>
		<description><![CDATA[Usually one of the last things I do before shipping a major product release is add in some sort of registration system. It is an unfortunate, yet necessary evil that adds nothing to the user experience, but helps keep honest users honest. I never implement registration systems thinking they will be immune to crackers and [...]]]></description>
			<content:encoded><![CDATA[<p>Usually one of the last things I do before shipping a major product release is add in some sort of registration system.  It is an unfortunate, yet necessary evil that adds nothing to the user experience, but helps keep honest users honest.</p>

<p>I never implement registration systems thinking they will be immune to crackers and others who are destined to find a way to not pay for my software.  Instead, I opt to make a system that is the least amount of work for the user, as well as the least amount of maintenance effort for myself.</p>

<p><a href="http://www.secondgearsoftware.com/today/">Today 1.0</a> and <a href="http://www.secondgearsoftware.com/checkoff/">Check Off 4</a> both make use of the <a href="http://github.com/bdrister/AquaticPrime/">AquaticPrime</a> framework.  AquaticPrime uses RSA encryption and generates license files.  I liked it because it was dead simple to setup on my end, but the concept of a license file has proved to be a support nightmare for anyone that is not a well versed computer user.  The fact is people expect serial numbers and when you email them a file with a strange extension on it, they aren&#8217;t really sure what to do.<sup>1</sup> <a href="http://github.com/fraserhess/boutique">Cocoa Boutique</a> aims to make the usage of AquaticPrime less painful for the end user by hiding the license file process from the user, but it currently requires using Paypal as your payment processor. </p>

<p>With <a href="http://www.secondgearsoftware.com/today/">Today 2.0</a> I opted to implement a traditional serial number system similar to what you&#8217;d find on the back of a shrink wrapped disc.  The support load in terms of registration issues for Today has dropped significantly, but I still run into a few users a week who have issues with typing in their serial number due to not being able to differentiate between <em>O</em> and <em>0</em> or <em>I</em> and <em>l</em>.   Telling the user they can just copy and paste the serial from their email into Today solves the issue, but it&#8217;s still frustrating that this is one of the first experiences the user has right after paying for my product.</p>

<p>This all has gotten me thinking about why we are still using things like license files or arbitrary strings of letters and numbers as the way of verifying a user has purchased our software.  It seems like there should be a better identifier for a user to validate their software purchase.  </p>

<p>This is what I had in mind:</p>

<ol>
<li>User purchases a copy of Product X from the Second Gear store.</li>
<li>Upon successful purchase, the user can then enter their email address into a registration dialog.</li>
<li>The app will ping home, validate that the user has indeed purchased the software, and mark it as registered.</li>
</ol>

<p>A single network transaction to validate the user.  No per-seat licenses or periodic phoning home a la Adobe or Microsoft.  The idea behind this is that a user&#8217;s email address is easier to remember and type rather than a string of random characters and numbers.  </p>

<p>I chirped up on Twitter <a href="http://twitter.com/justin/status/8198914506">about this</a> and got quite a few responses that I wanted to highlight and respond to.  </p>

<p>Justin Pennington <a href="http://twitter.com/penningtonj/status/8199083277">writes</a>:</p>

<blockquote>
  <p>@justin I agree but think the reason is because of having to keep that server side process up forever in order for the app to work.</p>
</blockquote>

<p>It&#8217;s honestly not that much work I wouldn&#8217;t think. A PHP script that takes an email address plus a product identifier and returns a pass/fail status is minimal effort both in terms of development and maintenance.  </p>

<p>The forever aspect of software is not something I really take too seriously.  There is very little software that I was using five years ago that I&#8217;m still using today.  I&#8217;ve purchased upgrades or just found a better workflow.  If need be, you could offer unlocked copies of previous releases to users who request them, or if you plan to go out of business or discontinue the product, offer an unlocked copy somewhere.  </p>

<p>Alastair Houghton of Coriolis <a href="http://twitter.com/alastairh/status/8199182677">tweets</a>:</p>

<blockquote>
  <p>@justin That’s what we do here; it causes far fewer problems and very few people mind the minor inconvenience of initial activation</p>
</blockquote>

<p>I recently reinstalled <a href="http://www.coriolis-systems.com/iPartition.php">iPartition</a> on my Mac mini, and the process Coriolis has in place is seamless.  I honestly can&#8217;t remember how it worked, which is a testament to how easy it is for honest, paid users.  Coriolis goes a step further by having user accounts that are tied to each purchase.  It&#8217;s a bit more work on the server side, but it seems to be working well for them.</p>

<p>Daniel Jalkut <a href="http://twitter.com/danielpunkass/status/8199352724">chimes in</a>:</p>

<blockquote>
  <p>@justin Serial numbers are simple and allow customers to activate their own purchased software at any time under their own control.</p>
</blockquote>

<p>This is actually the biggest reason I have against the idea of using an email address or order number as the system for registration.  </p>

<p><a href="http://twitter.com/pbur/status/8199810875">Patrick Burleson</a> and <a href="http://www.twitlonger.com/show/59jf9">Steve Streza</a> says something similar:</p>

<blockquote>
  <p>@justin My guess would be that email addresses are easy to guess. If someone knows I own a product and knows my email: free registration.</p>
</blockquote>

<p>My initial response to this was that it&#8217;s just as easy for someone to pass around the user&#8217;s serial number, but this could be afford a larger uptick in blind piracy.  If I knew that Patrick had a copy of FancyApp 1.0, I could download the trial, test out his email address and possibly have a free copy.  </p>

<p>The workaround for this could be to replace the email address with the Order # as the identifier, but I&#8217;m not sure how much of an upgrade that is versus serial numbers as the possibility of mistyping still exists.  Not to mention that order numbers are tied to your purchasing system, which may be a problem longer term.</p>

<p>Nick Peelman brings up the <a href="http://twitter.com/peelman/status/8200948567">enterprise</a> <a href="http://twitter.com/peelman/status/8200962407">angle</a>:</p>

<blockquote>
  <p>Please please please remember some form of enterprise activation&#8230; no matter how insignificant you think your app is in enterprise, help out the guys running a managed environment :)</p>
</blockquote>

<p>This is something I hadn&#8217;t considered, and a valid point.  I&#8217;m honestly not sure of a good way to handle this without adding a ton of infrastructure work on my end for a small use case.  </p>

<p>I am honestly not sure if there is a better system than the traditional serial, but it&#8217;s certainly something to ponder.</p>
<ol class="footnotes"><li id="footnote_0_415" class="footnote">It should be noted that these people also don&#8217;t read the instructions you provide that explain exactly what to do with the file.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/01/25/serial-numbers-are-dead-long-live-serials/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSStatusItem Not Supported By VoiceOver</title>
		<link>http://carpeaqua.com/2010/01/24/nsstatusitem-not-supported-by-voiceover/</link>
		<comments>http://carpeaqua.com/2010/01/24/nsstatusitem-not-supported-by-voiceover/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 00:20:02 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[accessibility]]></category>
		<category><![CDATA[voiceover]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=407</guid>
		<description><![CDATA[One of the my professional goals for 2010 is to improve the accessibility support of Check Off and Today. Martin Pilkington put the bug in my ear almost a year ago when he pledged to make all of his products accessible. Minim 2 is in fact one of the products I&#8217;ve been using as a [...]]]></description>
			<content:encoded><![CDATA[<p>One of the my professional goals for 2010 is to improve the accessibility support of <a href="http://www.secondgearsoftware.com/checkoff/">Check Off</a> and <a href="http://www.secondgearsoftware.com/today/">Today</a>.  Martin Pilkington put the <a href="http://www.mcubedsw.com/blog/index.php/site/comments/the_accessible_mac/">bug in my ear</a> almost a year ago when he pledged to make all of his products accessible.  <a href="http://www.mcubedsw.com/software/minim">Minim 2</a> is in fact one of the products I&#8217;ve been using as a reference during this process.</p>

<p>Unfortunately I <a href="http://lists.apple.com/archives/accessibility-dev/2009/Apr/msg00007.html">discovered</a> a pretty significant road block when working on improving Check Off&#8217;s accessibility.  <code>NSStatusItem</code>, the class that inserts the check mark in the Mac&#8217;s menu bar, is not accessible via <a href="http://www.apple.com/accessibility/voiceover/">VoiceOver</a>.  Try it for yourself:</p>

<ol>
<li>Launch System Preferences -> Universal Access</li>
<li>Turn on VoiceOver</li>
<li>Hold down `Control-Option-m&#8217; to access the menu bar via VoiceOver.  You&#8217;ll be at the Apple menu.</li>
<li>Press the Left and Right arrow keys to navigate between the File menus.</li>
<li>Press `Control-Option-m&#8217; again.  If you have them, you&#8217;ll jump to the standard OS X menu items like Airport, battery status and the clock.</li>
<li>Press `Control-Option-m&#8217; again to access Spotlight&#8217;s menu.</li>
</ol>

<p>Notice how VoiceOver skipped over your third-party menu items like <a href="http://www.secondgearsoftware.com/checkoff/">Check Off</a>, <a href="http://www.smileonmymac.com/TextExpander/">TextExpander</a> or <a href="http://www.red-sweater.com/fastscripts/">FastScripts</a>?  That&#8217;s not good.  In essence there is no way for a user to get access to these menu items without using the mouse or establishing a hot key to toggle them.</p>

<p>The Apple menu extras get VoiceOver support due to them using the private <code>NSMenuExtra</code> class.  Besides accessibility, <code>NSMenuExtra</code> items are draggable by holding down the Command key and moving them left or right.  The disparities between <code>NSStatusItem</code> and <code>NSMenuExtra</code> were discussed back in the Jaguar and Panther eras, and sadly it doesn&#8217;t seem the two have moved any closer to being alike.</p>

<p>At this point, Check Off 4.1 will be fully accessible, save for the menu extra which is out of my hands.  I would like to see Apple add accessibility support to the <code>NSStatusItem</code> class in a 10.6 point release, but I won&#8217;t hold my breath.   If this is an issue for you as a developer or user, I encourage you to dupe this Radar bug. </p>

<ul>
<li>OpenRadar: <a href="http://openradar.appspot.com/6832098">OS X 10.5: Status Items created with NSStatusItem are not VoiceOver accessible</a></li>
<li><a href="rdar://5037324">rdar://5037324</a></li>
</ul>

<p><strong>Update:</strong> As Martin Pilkington <a href="http://twitter.com/pilky/status/8131416250">pointed out</a>, it&#8217;s actually <code>NSStatusBar</code> that isn&#8217;t accessible.  Semantics aside, the issue remains as of Mac OS X 10.6.2.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/01/24/nsstatusitem-not-supported-by-voiceover/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial 1.4&#8217;s schemes extension</title>
		<link>http://carpeaqua.com/2009/12/09/mercurial-1-4s-schemes-extension/</link>
		<comments>http://carpeaqua.com/2009/12/09/mercurial-1-4s-schemes-extension/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 04:49:20 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=315</guid>
		<description><![CDATA[Mercurial 1.4.1 was released last week. It&#8217;s obviously a minor update compared to what 1.4 was, but it does include a really neat built-in extension: schemes Let&#8217;s say you are like me and want to push your code up to your project&#8217;s Kiln repository. This involves typing something along the lines of: hg push "https://justinw@secondgear.fogbugz.com/kiln/repo/products/group/today" [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mercurial.selenic.com/wiki/WhatsNew#A1.4.1_-_2009-12-01">Mercurial 1.4.1</a> was released last week.  It&#8217;s obviously a minor update compared to what 1.4 was, but it does include a really neat built-in extension: <a href="http://mercurial.selenic.com/wiki/SchemesExtension">schemes</a></p>

<p>Let&#8217;s say you are like me and want to push your code up to your project&#8217;s <a href="http://www.fogcreek.com/Kiln/">Kiln</a> repository.    This involves typing something along the lines of:</p>

<pre><code>hg push "https://justinw@secondgear.fogbugz.com/kiln/repo/products/group/today"
</code></pre>

<p>Disregard the fact that Kiln URLs are reek of Linux or Windows guy cruft.  That&#8217;s obviously a lot to type out.  With schemes, you can shrink it a bit.  </p>

<p>Add the following to your <code>.hgrc</code> file.</p>

<pre><code>[extensions]
hgext.schemes=

[schemes]
k = https://justinw@secondgear.fogbugz.com/kiln/repo/products/group/
</code></pre>

<p>Now instead of typing out that long URL, you can type out the following:</p>

<pre><code>hg push k://today
</code></pre>

<p>There are already predefined schemes entries for bitbucket (<code>bb</code>) and Google Code (<code>gcode</code>) repositories.  Couple this with <a href="http://smileonmymac.com/TextExpander/">TextExpander</a> and you have some seriously minimalist typing.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2009/12/09/mercurial-1-4s-schemes-extension/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clang. Garbage Collection. Leopard. Boom.</title>
		<link>http://carpeaqua.com/2009/10/22/clang-garbage-collection-leopard-boom/</link>
		<comments>http://carpeaqua.com/2009/10/22/clang-garbage-collection-leopard-boom/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 17:22:23 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[clang]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[garbage-collection]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=257</guid>
		<description><![CDATA[I ran into a pretty frustrating bug earlier this week. A few weeks ago I decided to flip the switch from GCC 4.2 to Clang 1.0 for building Check Off. Everything seemed to be working in my testing on my development machine, but as I was doing my Mac OS X Leopard sanity check &#38; [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into a pretty frustrating bug earlier this week.  A few weeks ago I decided to flip the switch from GCC 4.2 to Clang 1.0 for building <a href="http://www.secondgearsoftware.com/checkoff/">Check Off</a>.  Everything seemed to be working in my testing on my development machine, but as I was doing my Mac OS X Leopard sanity check &amp; testing I noticed that I was running into some pretty frustrating crashes and Console messages related when trying to fire up the preference pane.  </p>

<pre><code>10/15/09 3:09:25 PM Check Off[197] *** -[NSCFDictionary unregisterHotKey:]: unrecognized selector sent to instance 0x1086b00 
</code></pre>

<p><code>unRegisterHotKey</code> is a method in <a href="http://github.com/carpeaqua/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m">SGHotKeyCenter</a> and it certainly isn&#8217;t related to <code>SCFDictionary</code>, <code>NSCFString</code> or any other method I saw it being applied to.  </p>

<p>I fumbled with this for a while thinking that i had made a change in my code somewhere to cause the memory to be smashed a bit too soon, but kept coming up with no logical conclusion as to why the code worked without issue in Snow Leopard, but failed miserably in Leopard. </p>

<p>Long story short, I found the answer on the <a href="http://lists.apple.com/archives/objc-language/2009/Sep/msg00002.html">objc-language</a> list from Bill Bumgarner:</p>

<blockquote>
  <p>The problem is that Clang generates the wrong write barrier for the global assignment; right for Snow Leopard, incompatible with Leopard.</p>
</blockquote>

<p>If you look in SGHotKeyCenter, the <code>sharedInstance</code> is indeed a static global, and is being eaten alive far too soon by the collector.  </p>

<pre><code>...
static SGHotKeyCenter *sharedCenter = nil;

@implementation SGHotKeyCenter

+ (void)initialize {
...
</code></pre>

<p>There are two workarounds for the issue:</p>

<ol>
<li>Switch off of Clang until the issue is resolved by Apple.  GCC 4.2 works just fine.  </li>
<li><p>Use  <code>NSGarbageCollector</code> to disable collection on the pointer after assignment.  </p>

<pre><code>[[NSGarbageCollector defaultCollector] disableCollectorForPointer:sharedCenter];
</code></pre></li>
</ol>

<p>Hopefully this post will help a few other developers not waste a day&#8217;s work trying to figure out what was causing such a weird error.  </p>

<p>Here&#8217;s your Radar:</p>

<ul>
<li><a href="rdar://problem/7326965">rdar://problem/7326965</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2009/10/22/clang-garbage-collection-leopard-boom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create Amazon Affiliate Link.service</title>
		<link>http://carpeaqua.com/2009/09/13/create-amazon-affiliate-link-service/</link>
		<comments>http://carpeaqua.com/2009/09/13/create-amazon-affiliate-link-service/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 17:58:48 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[services]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=224</guid>
		<description><![CDATA[Ever since Gruber linked to the new Mac OS X Automation site, I&#8217;ve been a bit obsessed with finding ways to automate workflows and tedious tasks I do on my Mac. With Snow Leopard&#8217;s newly enhanced services functionality, it&#8217;s much easier to do than ever before. One thing I&#8217;ve long wanted to automate was the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://carpeaqua.com/wp-content/uploads/2009/09/amazon_service.png" alt="amazon_service.png" class="center" /></p>

<p>Ever since Gruber <a href="http://daringfireball.net/linked/2009/08/27/macosx-automation">linked</a> to the new <a href="http://www.macosxautomation.com/">Mac OS X Automation</a> site, I&#8217;ve been a bit obsessed with finding ways to automate workflows and tedious tasks I do on my Mac.  With Snow Leopard&#8217;s newly enhanced services functionality, it&#8217;s much easier to do than ever before.  </p>

<p>One thing I&#8217;ve long wanted to automate was the creation of clean Amazon affiliate URLs.  A while back Amazon offered affiliate users the ability to create links from within Amazon itself using a bar along the top of the site, but the URLs it produces are far from clean.   For example, this is the link Amazon provides for it&#8217;s Kindle through the Associates <em>Link To This Page</em> script.</p>

<p><code>
http://www.amazon.com/gp/product/B00154JDAI?ie=UTF8&amp;tag=carpeaqua-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B00154JDAI"
</code></p>

<p>There is a lot of cruft in the URL that I don&#8217;t want to paste into MarsEdit, an email or wherever else I&#8217;m linking to a product page.  What&#8217;s puzzling is that to get to the page, you really only need to append <code>"/dp/"</code>, the product ID and your tracking ID for it to be a valid URL.</p>

<p><code>

http://www.amazon.com/dp/B00154JDAI/ref=nosim/carpeaqua-20

</code></p>

<p>I&#8217;ve usually worked around this by copying the Amazon created URL to my clipboard, pasting it into BBEdit, cleaning it up and then expanding my associate ID using <a href="http://smileonmymac.com/textexpander/">TextExpander</a>.  With Services, I can automate this down to a single step.</p>

<p>I created a Safari service that allows me to select the product ID from any Amazon page URL and create an affiliate link from it.  The clean, affiliated URL is then copied to my clipboard so I can paste it in whatever application I desire.  </p>

<p>Here&#8217;s what to do:</p>

<ol>
<li>Open Automator and create a new Service.</li>
<li>Set the service to receive <em>selected text</em> in <em>Safari</em></li>
<li>Drag the &#8220;Run AppleScript&#8221; automator action into your workflow</li>
<li>Copy the script below in.  Be sure to replace the <code>"ref=nosim/carpeaqua-20"</code> line with your own referral ID.  </li>
</ol>

<pre>
<code>
on run {input, parameters}
    set the_url to "http://www.amazon.com/dp/" &#038; input &#038; "/ref=nosim/carpeaqua-20"
    set the clipboard to the_url
    return the_url
end run
</code>
</pre>

<ol>
<li>Save your service.  </li>
</ol>

<p>To test the service out, head to any Amazon URL and select the product ID (the string after <em>/dp/</em>).  Right-click on the text and run your newly created service.  A short, clean and affiliated Amazon URL is now on your clipboard.</p>

<p>The workflow on this isn&#8217;t perfect given that you can&#8217;t just copy in the entire URL, but given AppleScript&#8217;s lack of regular expression functionality, this was the best route I could think of taking. </p>

<p>If you find this service useful you could make me rich by either buying yourself a Kindle using <a href="http://www.amazon.com/dp/B00154JDAI/ref=nosim/carpeaqua-20">this link</a> or (even better) <a href="http://www.amazon.com/dp/B00154JDAI/ref=nosim/carpeaqua-20">buy me one</a>.  </p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2009/09/13/create-amazon-affiliate-link-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic OCR Conversion with PDFpen and Folder Actions</title>
		<link>http://carpeaqua.com/2009/01/08/automatic-ocr-conversion-with-pdfpen-and-folder-actions/</link>
		<comments>http://carpeaqua.com/2009/01/08/automatic-ocr-conversion-with-pdfpen-and-folder-actions/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 07:01:45 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[pdfpen]]></category>
		<category><![CDATA[s510m]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=62</guid>
		<description><![CDATA[One of my new years resolutions was to turn Second Gear into a paperless office. To start that resolution off right I recently picked up a Fujitsu S510M. The S510M comes with a full version of Adobe Acrobat Professional, but I&#8217;ve always found Acrobat to be too bloated for me to use without wanting to [...]]]></description>
			<content:encoded><![CDATA[<p>One of my new years resolutions was to turn Second Gear into a paperless office.  To start that resolution off right I recently picked up a <a href="http://www.amazon.com/gp/product/B000WJCX18?ie=UTF8tag=carpeaqua-20linkCode=as2camp=1789creative=390957creativeASIN=B000WJCX18">Fujitsu S510M</a>.  The S510M comes with a full version of Adobe Acrobat Professional, but I&#8217;ve always found Acrobat to be too bloated for me to use without wanting to pull out hair.  </p>

<p>SmileOnMyMac&#8217;s <a href="http://smileonmymac.com/PDFpen/">PDFpen 4</a> has the ability to OCR documents and uses far less resources doing so than Acrobat.  I&#8217;ve built a modified version of Joe Kissel&#8217;s <a href="http://www.macworld.com/article/60229/2007/10/nov07geekfactor.html">OCR It</a> scripts for Acrobat to use PDFpen instead.  </p>

<p>To use it, do the following:</p>

<ol>
<li>Download the script <a href="http://carpeaqua.com/wp-content/uploads/2009/01/ocr-this-pdfpen.zip">from here</a>.  </li>
<li>Unzip and place the <code>OCR This (PDFpen)</code> script in <code>/Library/Scripts/Folder Action Scripts/</code></li>
<li>Create a folder on your Desktop or any other location you&#8217;d like.</li>
<li>Attach a folder action to the folder you created and select the <code>OCR This (PDFpen)</code> script as the action to perform.  </li>
</ol>

<p>Now whenever you pop a PDF into this folder, it will open in PDFpen, perform an OCR conversion, save the file and close it out.</p>

<p>If you find this script useful please do consider purchasing a license for <a href="http://secondgearsoftware.com/today">Today</a> to show your thanks.  </p>

<p><strong>Updated July 1, 2009</strong> - I&#8217;ve updated the script to require PDFpen 4.1.4, which has some new OCR functionality in the AppleScript dictionary.  No more GUI scripting!</p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2009/01/08/automatic-ocr-conversion-with-pdfpen-and-folder-actions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Just F&#8217;ing Ship It</title>
		<link>http://carpeaqua.com/2008/04/23/just-fing-ship-it/</link>
		<comments>http://carpeaqua.com/2008/04/23/just-fing-ship-it/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 17:00:00 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Advice]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Opinion]]></category>
		<category><![CDATA[shipping]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=34</guid>
		<description><![CDATA[When I first decided to pursue Today as a new development venture I knew going in that I didn&#8217;t want to spend 6 months building every possible feature I could think of into it. Not only was it not financially viable, but it&#8217;s counter-productive in a sense. I&#8217;m a big fan of foundation releases. In [...]]]></description>
			<content:encoded><![CDATA[<p>When I first decided to pursue Today as a new development venture I knew going in that I didn&#8217;t want to spend 6 months building every possible feature I could think of into it. Not only was it not financially viable, but it&#8217;s counter-productive in a sense.</p>

<p>I&#8217;m a big fan of foundation releases. In other words, release the bare minimum you possibly can to constitute a 1.0 and then let your users help decide the direction your application ships.</p>

<p>When I shipped 1.0 yesterday, I had 5 feature ideas written down. Now that thousands of people have downloaded and tried the application, I have increased that number 5x. More importantly, it&#8217;s great ideas that I never thought of myself.</p>

<p>Doing solo development can leave you in a bubble. Don&#8217;t worry if your application isn&#8217;t 100% perfect (Today certainly isn&#8217;t). Just ship what you can in 60-90 days and let actual, paying users help shape the direction of your product. A year from now, rather than having a 1.0, you&#8217;ll have a 2.0 that is so much better.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2008/04/23/just-fing-ship-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
