<?xml version="1.0" encoding="UTF-8"?>
<rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>carpeaqua by Justin Williams</title>
	
	<link>http://carpeaqua.com</link>
	<description />
	<lastBuildDate>Fri, 05 Mar 2010 20:19:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain="carpeaqua.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/carpeaqua" /><feedburner:info uri="carpeaqua" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>First &amp; 20: Justin Williams</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/-p22nN8wtUQ/</link>
		<comments>http://carpeaqua.com/2010/03/05/first-20-justin-williams/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 20:19:08 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=504</guid>
		<description><![CDATA[Ever wonder what apps are on my iPhone&#8217;s homescreen?  Now you know.  
]]></description>
			<content:encoded><![CDATA[<p>Ever wonder what apps are on my iPhone&#8217;s homescreen?  Now you know.  </p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/-p22nN8wtUQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/03/05/first-20-justin-williams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.firstand20.com/homescreens/justin-williams/</feedburner:origLink></item>
		<item>
		<title>Building A Modern Cocoa App</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/XPr0TU-LfSo/building_a_modern_cocoa_app</link>
		<comments>http://carpeaqua.com/2010/03/04/building-a-modern-cocoa-app/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 18:21:06 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=502</guid>
		<description><![CDATA[Martin Pilkington responds to my blog post yesterday on a modern app architecture 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 [...]]]></description>
			<content:encoded><![CDATA[<p>Martin Pilkington responds to my blog post yesterday on a modern app architecture 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 <a href="http://rentzsch.github.com/mogenerator/">MOGenerator</a> to generate the Core Data classes.  My personal coding style is somewhere between my sample and his.  I highly recommend checking out both and drawing your own conclusions.</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/XPr0TU-LfSo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/03/04/building-a-modern-cocoa-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mcubedsw.com/blog/index.php/site/comments/building_a_modern_cocoa_app</feedburner:origLink></item>
		<item>
		<title>Getting Started With Core Data, Bindings and NSViewController</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/edxa7-fQJkg/</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 [...]]]></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><img src="http://feeds.feedburner.com/~r/carpeaqua/~4/edxa7-fQJkg" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://carpeaqua.com/2010/03/03/getting-started-with-core-data-bindings-and-nsviewcontroller/</feedburner:origLink></item>
		<item>
		<title>ProfitTrain</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/sA3cLJKD-a0/</link>
		<comments>http://carpeaqua.com/2010/03/01/profittrain/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 15:59:16 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=489</guid>
		<description><![CDATA[Congrats to Mike Zornek on shipping ProfitTrain, a major update to his invoice tracking software.  The icon is gorgeous.
]]></description>
			<content:encoded><![CDATA[<p>Congrats to Mike Zornek on shipping ProfitTrain, a major update to his invoice tracking software.  The icon is gorgeous.</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/sA3cLJKD-a0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/03/01/profittrain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://clickablebliss.com/profittrain/</feedburner:origLink></item>
		<item>
		<title>Tips for Presenting like a Prince</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/92E4F4SGoF0/tips-presenting-prince</link>
		<comments>http://carpeaqua.com/2010/02/28/tips-for-presenting-like-a-prince/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 16:48:10 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[nsconference]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=487</guid>
		<description><![CDATA[Drew McCormack&#8217;s list of excellent tips for presenting in public.  As I opined on Twitter, I actually prefer to present without slides whenever possible because I think people become too easily distracted reading the text of a slide.  More than that, it&#8217;s something else for me to have to manage on the stage [...]]]></description>
			<content:encoded><![CDATA[<p>Drew McCormack&#8217;s list of excellent tips for presenting in public.  As I opined <a href="http://twitter.com/justin/status/9782717223">on Twitter</a>, I actually prefer to present without slides whenever possible because I think people become too easily distracted reading the text of a slide.  More than that, it&#8217;s something else for me to have to manage on the stage that&#8217;s not the actual message itself.</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/92E4F4SGoF0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/28/tips-for-presenting-like-a-prince/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.macresearch.org/tips-presenting-prince</feedburner:origLink></item>
		<item>
		<title>Dog Spanner Proposes NSManagedObjectOperation</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/pTqiOn8-AwM/brent-switching-away-from-core-data</link>
		<comments>http://carpeaqua.com/2010/02/27/dog-spanner-proposes-nsmanagedobjectoperation/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 01:13:13 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=477</guid>
		<description><![CDATA[Wolf reminisces on EOF&#8217;s ability to drop down into raw SQL operations and a more modern alternative. 


  A better method would be if Core Data&#8217;s NSPersistentStoreCoordinator offered a method that accepted an NSPredicate or NSFetchRequest (I haven’t decided which would be better) along with an NSArray of NSManagedObjectOperations.
  
  NSManagedObjectOperation would [...]]]></description>
			<content:encoded><![CDATA[<p>Wolf reminisces on EOF&#8217;s ability to drop down into raw SQL operations and a more modern alternative. </p>

<blockquote>
  <p>A better method would be if Core Data&#8217;s NSPersistentStoreCoordinator offered a method that accepted an NSPredicate or NSFetchRequest (I haven’t decided which would be better) along with an NSArray of NSManagedObjectOperations.</p>
  
  <p>NSManagedObjectOperation would be a new, lightweight class that declaratively describes how a matched object should be operated upon. The idea is it would be easily compiled down to raw SQL, yet still be compatible with all the other (and future) store types.</p>
</blockquote>

<p>One thing I love about Wolf Rentzsch and <a href="http://weblog.bignerdranch.com/">Aaron</a> is their love for a 10 year old persistence framework for WebObjects.  What couldn&#8217;t it do?</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/pTqiOn8-AwM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/27/dog-spanner-proposes-nsmanagedobjectoperation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://rentzsch.tumblr.com/post/414252963/brent-switching-away-from-core-data</feedburner:origLink></item>
		<item>
		<title>BNRPersistence</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/QpSdW0YH0Tc/BNRPersistence</link>
		<comments>http://carpeaqua.com/2010/02/27/bnrpersistence/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 01:07:47 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=475</guid>
		<description><![CDATA[Speaking of not Core Data, Aaron Hillegass wrote a fairly impressive wrapper for Tokyo Cabinet that he demoed at NSConference.  I wonder if this might have been a good alternative for Brent?
]]></description>
			<content:encoded><![CDATA[<p>Speaking of not Core Data, Aaron Hillegass wrote a fairly impressive wrapper for Tokyo Cabinet that he demoed at NSConference.  I wonder if this might have been a good alternative for Brent?</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/QpSdW0YH0Tc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/27/bnrpersistence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://github.com/hillegass/BNRPersistence</feedburner:origLink></item>
		<item>
		<title>On switching away from Core Data</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/-ZdmWO7BWmc/on_switching_away_from_core_data</link>
		<comments>http://carpeaqua.com/2010/02/27/on-switching-away-from-core-data/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 01:07:20 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=473</guid>
		<description><![CDATA[Brent Simmons on why he switched from Core Data to raw SQLite:


  In Core Data, I had to loop through the list, change the status for each individual item. The list could be up to 10,000 items long. Not a good idea. 
  
  This is a very database-y operation. With one [...]]]></description>
			<content:encoded><![CDATA[<p>Brent Simmons on why he switched from Core Data to raw SQLite:</p>

<blockquote>
  <p>In Core Data, I had to loop through the list, change the status for each individual item. The list could be up to 10,000 items long. Not a good idea. </p>
  
  <p>This is a very database-y operation. With one query the app can set the status for a whole bunch of items at once, without having to instantiate them as objects: update newsItems set read = 1 where&#8230;</p>
</blockquote>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/-ZdmWO7BWmc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/27/on-switching-away-from-core-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://inessential.com/2010/02/26/on_switching_away_from_core_data</feedburner:origLink></item>
		<item>
		<title>Walk and Code</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/g2n-T-XdjTU/walk-and-code</link>
		<comments>http://carpeaqua.com/2010/02/26/walk-and-code/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 12:54:50 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=471</guid>
		<description><![CDATA[Doug Bradbury shows how he converted a treadmill into a walking workstation.  

(Via Scott Stevenson)
]]></description>
			<content:encoded><![CDATA[<p>Doug Bradbury shows how he converted a treadmill into a walking workstation.  </p>

<p>(Via <a href="http://twitter.com/scottstevenson/status/9667931015">Scott Stevenson</a>)</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/g2n-T-XdjTU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/26/walk-and-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.8thlight.com/articles/2010/2/25/walk-and-code</feedburner:origLink></item>
		<item>
		<title>An Interview with Justin Williams, Second Gear Software</title>
		<link>http://feedproxy.google.com/~r/carpeaqua/~3/GvWRgVZiz4A/justin-williams-second-gear.html</link>
		<comments>http://carpeaqua.com/2010/02/26/an-interview-with-justin-williams-second-gear-software/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 05:34:00 +0000</pubDate>
		<dc:creator>Justin Williams</dc:creator>
				<category><![CDATA[Linked]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://carpeaqua.com/?p=469</guid>
		<description><![CDATA[An interview with yours truly on the type of marketing stuff I do for Second Gear.
]]></description>
			<content:encoded><![CDATA[<p>An interview with yours truly on the type of marketing stuff I do for Second Gear.</p>
<img src="http://feeds.feedburner.com/~r/carpeaqua/~4/GvWRgVZiz4A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://carpeaqua.com/2010/02/26/an-interview-with-justin-williams-second-gear-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.karelia.com/mac_indie_marketing/justin-williams-second-gear.html</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.302 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-03-16 11:11:11 -->
