<?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>Cocoa Is My Girlfriend &#187; Advanced</title>
	<atom:link href="http://www.cimgf.com/category/advanced/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cimgf.com</link>
	<description>Taglines are for Windows programmers</description>
	<lastBuildDate>Thu, 15 Jul 2010 21:20:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Re-Ordering NSFetchedResultsController</title>
		<link>http://www.cimgf.com/2010/06/05/re-ordering-nsfetchedresultscontroller/</link>
		<comments>http://www.cimgf.com/2010/06/05/re-ordering-nsfetchedresultscontroller/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 23:06:00 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Core Data]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=995</guid>
		<description><![CDATA[So Marcus is the Core Data guy, but I&#8217;ve been working with it a good bit myself lately and was recently faced with having to add re-ordering for a list of entities in a UITableView. The methods I found online for accomplishing this all suggested using an NSMutableArray as the data source for the table [...]]]></description>
			<content:encoded><![CDATA[<p>So Marcus is the Core Data guy, but I&#8217;ve been working with it a good bit myself lately and was recently faced with having to add re-ordering for a list of entities in a UITableView. The methods I found online for accomplishing this all suggested using an NSMutableArray as the data source for the table view. That will work, but I came up with another method, though similar, that achieved what I need without having to switch from using my NSFetchedResultsController as the data source behind the UITableView. In the end, I did use an NSMutableArray, however, I end up using it just to take advantage of its indexing. Read on to see what I mean.
<span id="more-995"></span></p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2010/05/FavoriteThings.zip'>Download the source code for the Favorite Things project.</a></p>

<h2>A Few of My Favorite Things</h2>

<p>My kids have been watching <em>The Sound of Music</em> lately, but that&#8217;s not what made me decide to use a list of favorite things as the premise of my example code (sorry if that just got a Julie Andrews song stuck in your head. For the rest of you who have no idea what I&#8217;m talking about, move along. Nothing to see here). What made me think of it is the fact that your favorite things might need re-ordered from time to time. A list of my favorite things all seem to be Apple products as the example code shows. Yours might be something else. I&#8217;ve added a method at the start of this example app to populate the Core Data database with a list of a few of my favorite things (&#8220;&#9835;&#9835;&#8230;when the dog bites, when the bee stings, when you&#8217;re feeling sad &#9835;&#9835;&#8230; ooops, sorry). I first fetch the list and if it&#8217;s empty I go ahead and populate the Core Data data store. Here is that code:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>loadFavoriteThingsData;
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>fetchedResultsController fetchedObjects<span style="color: #002200;">&#93;</span> count<span style="color: #002200;">&#93;</span> &gt; <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>
    <span style="color: #a61390;">return</span>;
&nbsp;
  <span style="color: #400080;">NSManagedObject</span> <span style="color: #002200;">*</span>favoriteThing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;MacBook Pro&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingName&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;A powerful computer that will burn your lap.&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingDescription&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  favoriteThing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iPad&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingName&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;That's a really big iPod!&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingDescription&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  favoriteThing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iPhone&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingName&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;A computer that thinks it's a phone.&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingDescription&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  favoriteThing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;iPod&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingName&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Also known as the iPad nano.&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingDescription&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">3</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  favoriteThing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;WWDC Ticket&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingName&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;It sold out in eight days this year, you know?&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;thingDescription&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>favoriteThing setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">4</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>managedObjectContext save<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Our Core Data database will now be populated with some initial data so we&#8217;ll have something to see. Here is what the initial screen looks like:</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/favoritethings.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/favoritethings-161x300.png" alt="" title="favoritethings" width="161" height="300" class="alignleft size-medium wp-image-1001" /></a></p>

<h2>Display Order Attribute</h2>

<p>In order to implement re-ordering, your entity in your Core Data model will need a displayOrder attribute (you can call it whatever you want, but I&#8217;ve named mine displayOrder). This is an integer that will keep track of your indexes and is the field you will use to sort your results in the fetch request sort descriptor. Here is what the code looks like to fetch the entities using the displayOrder attribute as the sort descriptor:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSFetchedResultsController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fetchedResultsController
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>fetchedResultsController<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> fetchedResultsController;
&nbsp;
  <span style="color: #400080;">NSFetchRequest</span> <span style="color: #002200;">*</span>fetchRequest <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFetchRequest</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSEntityDescription</span> <span style="color: #002200;">*</span>entity <span style="color: #002200;">=</span> 
               <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> entityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FavoriteThing&quot;</span> 
                           inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>fetchRequest setEntity<span style="color: #002200;">:</span>entity<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #400080;">NSSortDescriptor</span> <span style="color: #002200;">*</span>sortDescriptor <span style="color: #002200;">=</span> 
              <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSSortDescriptor</span> alloc<span style="color: #002200;">&#93;</span> initWithKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span> 
                                          ascending<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>sortDescriptors <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> alloc<span style="color: #002200;">&#93;</span> 
                              initWithObjects<span style="color: #002200;">:</span>sortDescriptor, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;  
  <span style="color: #002200;">&#91;</span>fetchRequest setSortDescriptors<span style="color: #002200;">:</span>sortDescriptors<span style="color: #002200;">&#93;</span>;
&nbsp;
  NSFetchedResultsController <span style="color: #002200;">*</span>aFetchedResultsController <span style="color: #002200;">=</span> 
              <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSFetchedResultsController alloc<span style="color: #002200;">&#93;</span> initWithFetchRequest<span style="color: #002200;">:</span>fetchRequest 
                                                  managedObjectContext<span style="color: #002200;">:</span>managedObjectContext
                                                    sectionNameKeyPath<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> cacheName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ThingsCache&quot;</span><span style="color: #002200;">&#93;</span>;
  aFetchedResultsController.delegate <span style="color: #002200;">=</span> self;
  <span style="color: #002200;">&#91;</span>self setFetchedResultsController<span style="color: #002200;">:</span>aFetchedResultsController<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>aFetchedResultsController release<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>fetchRequest release<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>sortDescriptor release<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>sortDescriptors release<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">return</span> fetchedResultsController;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Your Core Data entity that you want to re-order should look something like this in the data model editor in Xcode:</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/05/coredatamodel.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/05/coredatamodel-300x215.png" alt="" title="coredatamodel" width="300" height="215" class="alignleft size-medium wp-image-1061" /></a></p>

<h2>Favorites Change</h2>

<p>This post is about re-ordering so here is the point. NSFetchedResultsController doesn&#8217;t have a built in way to re-order the results, so load them into an NSMutableArray, rearrange them there, and then re-iterate over the items once sorted setting each of their displayOrder field as you go. Then save the managed object context and you&#8217;re all re-ordered.</p>

<p>The reason we use an NSMutableArray is because we can insert and remove managed object pointers to/from the array without triggering any changes to the data store. When you make changes to the objects themselves the change is reflected immediately&#8211;which is often what we want, but sometimes we don&#8217;t as in this case. In <a href="http://www.amazon.com/Core-Data-Apples-API-Persisting/dp/1934356328/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1273621059&#038;sr=8-1">Marcus&#8217; Core Data book</a> he points out that you can keep KVO messages from being sent when you want to change a managed object&#8217;s attributes by calling <strong>-setPrimitiveValue:forKey</strong>, but it seemed simpler to me to just re-arrange the objects in an array, and then make the change to each of the object&#8217;s displayOrder attribute. Here is the code you use to re-order the results:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView 
moveRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSIndexPath</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>sourceIndexPath 
      toIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSIndexPath</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>destinationIndexPath;
<span style="color: #002200;">&#123;</span>  
  <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>things <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>fetchedResultsController fetchedObjects<span style="color: #002200;">&#93;</span> mutableCopy<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #11740a; font-style: italic;">// Grab the item we're moving.</span>
  <span style="color: #400080;">NSManagedObject</span> <span style="color: #002200;">*</span>thing <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self fetchedResultsController<span style="color: #002200;">&#93;</span> objectAtIndexPath<span style="color: #002200;">:</span>sourceIndexPath<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #11740a; font-style: italic;">// Remove the object we're moving from the array.</span>
  <span style="color: #002200;">&#91;</span>things removeObject<span style="color: #002200;">:</span>thing<span style="color: #002200;">&#93;</span>;
  <span style="color: #11740a; font-style: italic;">// Now re-insert it at the destination.</span>
  <span style="color: #002200;">&#91;</span>things insertObject<span style="color: #002200;">:</span>thing atIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>destinationIndexPath row<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #11740a; font-style: italic;">// All of the objects are now in their correct order. Update each</span>
  <span style="color: #11740a; font-style: italic;">// object's displayOrder field by iterating through the array.</span>
  <span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObject</span> <span style="color: #002200;">*</span>mo <span style="color: #a61390;">in</span> things<span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>mo setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span>i<span style="color: #002200;">++</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;displayOrder&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
&nbsp;
  <span style="color: #002200;">&#91;</span>things release<span style="color: #002200;">&#93;</span>, things <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>managedObjectContext save<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Further Considerations</h2>

<p>You may be thinking that if you iterate through every object in your results you&#8217;re actually loading them into memory. This is true, but not something to be concerned about for a couple reasons. First, the results were loaded into memory to display in the table view already. Also, in any table view where you are planning to re-order your results, it is highly unlikely that your list of objects will be very long as trying to re-order too many objects would just prove frustrating for your user and your design has just clearly demonstrated the need to be re-designed at that point anyhow.</p>

<h2>Finishing Up</h2>

<p>There are just a few more points I want to make before we&#8217;re done.</p>

<p>The project template I used is just the default navigation template along with Core Data for storage.</p>

<p>In order for the table view to display the detail text, you need to instantiate your UITableViewCells using the UITableViewCellStyleSubtitle constant. Here is the code to do so:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span>;
&nbsp;
UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
  cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITableViewCell alloc<span style="color: #002200;">&#93;</span> initWithStyle<span style="color: #002200;">:</span>UITableViewCellStyleSubtitle 
                                 reuseIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span><span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Finally, remember that you have to implement <strong>-canMoveRowAtIndexPath</strong> and return YES if you want the re-order control to display:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView canMoveRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSIndexPath</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Conclusion</h2>

<p>The <strong>NSFetchedResulsController</strong> in tandem with a simple <strong>NSMutableArray</strong> works great to provide re-ordering for your table views. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2010/05/FavoriteThings.zip'>Download the source code for the Favorite Things project.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/06/05/re-ordering-nsfetchedresultscontroller/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Adding Plugins to a Cocoa Application</title>
		<link>http://www.cimgf.com/2008/09/17/cocoa-tutorial-adding-plugins-to-a-cocoa-application/</link>
		<comments>http://www.cimgf.com/2008/09/17/cocoa-tutorial-adding-plugins-to-a-cocoa-application/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 17:45:11 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=272</guid>
		<description><![CDATA[A couple of weeks ago we discussed how to build frameworks and how to bundle them with a Cocoa application. This week we are going to build on that knowledge and add Plug-ins to a Cocoa application. Why are these topics linked? Generally, there are a few ways to add plug-ins to a Cocoa application. [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago we discussed <a href="http://www.cimgf.com/2008/09/04/cocoa-tutorial-creating-your-very-own-framework/">how to build frameworks and how to bundle them with a Cocoa application</a>.  This week we are going to build on that knowledge and add Plug-ins to a Cocoa application.</p>

<p><span id="more-272"></span></p>

<h2>Why are these topics linked?</h2>

<p>Generally, there are a few ways to add plug-ins to a Cocoa application.</p>

<h3>Scriptable plug-ins</h3>

<p>Scriptable plug-ins are probably the easiest to add to an application.  They exist in a known location where the application can load them and run them in the appropriate virtual machine.  This makes them fairly easy to construct even though the code to run them may be rather complicated.</p>

<h3>Publishing a Formal Protocol Plug-ins Interface</h3>

<p>This one is a bit more complicated.  The developer (you and me) publish a formal protocol that the plug-ins must adhere to.  This design works rather well but does not allow us, the application developer, to impart any functionality to the plug-ins easily.</p>

<h3>Publishing an Informal Protocol Plug-ins Interface</h3>

<p>This is very similar to the formal plug-ins above but a little more tricky.  Since the protocol is informal, we have to test for each method that we want to use in the plug-ins before we can use it.  Again, it does not make it very easy for us to impart functionality to the plug-ins.</p>

<h3>Publishing a Base Class Plug-ins Interface</h3>

<p>This is the hardest option I have found so far.  Not only do we have to give our plug-ins developers a header file but something to actually compile against.  However, with a base class we can easily impart functionality to our plug-ins without the plug-ins developer having to jump through <em>too many</em> hoops.</p>

<p>Creating a base class solution is where frameworks come in.  It makes it fairly trivial to hand off a base class to plug-ins developers when we give them a framework.  Therefore, we are going to add one class to the plug-ins we wrote previously with the following header:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> AbstractPlugin <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> 
<span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>name;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>fire<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>


<p>And since I like to make it stupidly easy for people, we are going to use the following implementation of the base &#8220;abstract&#8221; class:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;AbstractPlugin.h&quot;</span>
&nbsp;
<span style="color: #6e371a;">#define kErrFormat @&quot;%s not implemented in subclass %@&quot;</span>
<span style="color: #6e371a;">#define kExceptName @&quot;CIMGF&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> AbstractPlugin
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>name;
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>reason <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span>kErrFormat, 
    _cmd, <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">@throw</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSException</span> exceptionWithName<span style="color: #002200;">:</span>kExceptName 
                                 reason<span style="color: #002200;">:</span>reason 
                               userInfo<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>fire<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span> reason <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span>kErrFormat, 
    _cmd, <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">@throw</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSException</span> exceptionWithName<span style="color: #002200;">:</span>kExceptName 
                                 reason<span style="color: #002200;">:</span>reason 
                               userInfo<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>


<p>For every method that the subclass <strong>must</strong> override the abstract class will throw an exception if it is not overwritten with a polite message explaining what method in which class is missing.</p>

<h2>Building the plug-ins</h2>

<p>A plug-ins is effectively just a bundle, like a framework or an application.  Inside of the bundle is a Contents directory, MacOS directory (where the binary goes) and a Resources directory.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/bundlestructure.png" rel="lightbox" title="Bundle Structure">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/bundlestructure.png" width="50%" alt="Bundle Structure"/>

</a>
</div>

<p>Xcode has a template for building plug-ins that we can use to get started.  For this first plug-ins, we are going to just add it to our existing project as a new target.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/newproject.png" rel="lightbox" title="New Bundle Project">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/newproject.png" width="50%" alt="New Bundle Project"/>

</a>
</div>

<p>This new target is very similar to the Framework target that we built previously.  We want to drag it up into the Application&#8217;s target so that it is a dependency; this can also be done from the Get Info window.  We will also want to add the Framework product as a linked framework in the plug-ins.  The end result looks like this.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/targetstructure.png" rel="lightbox" title="Target Structure">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/targetstructure.png" width="50%" alt="Target Structure"/>

</a>
</div>

<p>Once we have the target set up, it is time to add some code.  Plug-ins needs to have either a main class defined or a main nib defined.  It is this definition that helps determine how to launch the bundle.  In our case, we will want to define a main class which will be explained below.  To define a main class (or nib), we need to look at the properties tab of the target.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/propertiestab.png" rel="lightbox" title="Properties Tab">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/propertiestab.png" width="50%" alt="Properties Tab"/>

</a>
</div>

<p>The next step is to create the main class for our plug-ins.  Since we are using a base class design for our plug-ins, our main class must extend the AbstractPlugin class and it needs to import the framework directly in the header.  For our example, our plug-ins is going to display a new window on the screen, therefore the header must also include a NSWindow attribute and since we want to programmatically close the window, a -closeWindow: IBAction.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
<span style="color: #6e371a;">#import &lt;Example/Example.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> PluginMainClass <span style="color: #002200;">:</span> AbstractPlugin 
<span style="color: #002200;">&#123;</span>
  IBOutlet <span style="color: #400080;">NSWindow</span> <span style="color: #002200;">*</span>mainWindow;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>closeWindow<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>


<p>Note that we are importing the framework which contains the AbstractPlugin super class we built earlier.</p>

<p>Once we have the main class defined it is time to build the user interface to go along with this plug-ins.  It is not a requirement that plug-ins have a user interface, they can be pure code instead.  However for the sake of completeness, we are going to add one for this example.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/pluginwindowstructure.png" rel="lightbox" title="Plug-ins Window Structure">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/pluginwindowstructure.png" width="50%" alt="Plug-ins Window Structure"/>

</a>
</div>

<p>The structure of the plug-ins nib is simple.  The file owner is the PluginMainClass we wrote previously and there is one window which we bind to the file owner.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/pluginwindow.png" rel="lightbox" title="Plug-ins Window">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/pluginwindow.png" width="50%" alt="Plug-ins Window"/>

</a>
</div>

<p>The window is also equally simple, just one button that binds back to the file owner&#8217;s -closeWindow: method.</p>

<p>The last step is to add a copy phase to our application.  Like the framework copy phase we built last time, this is a &#8220;Copy Files&#8221; build phase and we need to configure it to copy files to the &#8220;PlugIns&#8221; directory.  This is another top level directory next to Resources and Frameworks.  Once the build phase is added, drag the plug-ins product into that build phase.</p>

<p>With the window and the main class built we can compile the plug-ins and make sure everything is ready for inclusion into our application.  Once the app is built, we should see a copy of the plug-ins inside of the application bundle.  Now it is time to dynamically load the bundle.</p>

<p>The flow of loading bundles dynamically is as follows:</p>

<ol>
  <li>Find the paths of the bundles.</li>
  <li>Instantiate NSBundle objects for the paths.</li>
  <li>Execute the -load method on the bundle.</li>
  <li>Retrieve the principal class from the bundle.</li>
  <li>Instantiate an object from the principal class.</li>
</ol>

<p>And the code for this is as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>loadPlugins
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSBundle</span> <span style="color: #002200;">*</span>main <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>all <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>main pathsForResourcesOfType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bundle&quot;</span> 
                                   inDirectory<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;../PlugIns&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>availablePlugins <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">id</span> plugin <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #400080;">NSBundle</span> <span style="color: #002200;">*</span>pluginBundle <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #a61390;">in</span> all<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    pluginBundle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> bundleWithPath<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>pluginBundle load<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">Class</span> prinClass <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>pluginBundle principalClass<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>prinClass isSubclassOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>AbstractPlugin class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #a61390;">continue</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    plugin <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>prinClass alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>availablePlugins addObject<span style="color: #002200;">:</span>plugin<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>plugin release<span style="color: #002200;">&#93;</span>, plugin <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    pluginBundle <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #a61390;">return</span> availablePlugins;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>In this new method that we have added to the AppDelegate we first get a reference to the main bundle and we then request a path for every file in the PlugIns directory that has an extension of bundle.  With that array in hand we then start to loop over the array and construct a new NSBundle for each path.  Once the bundle is constructed we ask for it to load.  After the load, we grab its principal class, check to make sure we can use it, and construct an object from it.</p>

<p>Since we want to have a list of the loaded plug-ins, we throw this new object into an array that will be returned back from the method.  Once this method is complete we now have every plug-ins dynamically loaded and ready to use.  So lets use them!</p>

<p>We really want to call this method before the application has finished loading, therefore we need to add an -init method to our AppDelegate and load the plug-ins there.  This will guarantee that they are loaded before the UI with some obvious benefits.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>self setPlugins<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self loadPlugins<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Here are we calling our new -loadPlugins method and setting the returned array into a ivar.  This ivar will then be used by our UI once it loads to display a list of the plug-ins.</p>

<div style="text-align:center;">

<a href="http://www.cimgf.com/wp-content/uploads/2008/09/mainappwindow.png" rel="lightbox" title="Main Application Window">

<img src="http://www.cimgf.com/wp-content/uploads/2008/09/mainappwindow.png" width="50%" alt="Main Application Window"/>

</a>
</div>

<p>The main window has a pop up button with a list of the plug-ins using their inherited -name method for display.  When the run button is clicked, our application will find out which plug-ins were selected via the NSArrayController and call the inherited -run: method on the plug-ins with predictable results.</p>

<h2>Conclusion</h2>

<p>For clarity we did leave a few things out of this project.  For example, there is no code for unloading the plug-ins nor do we search the Application Support directory for user added plug-ins.  However these are easy to add based on the code that was included.</p>

<p>I should also note that we used the default extension for these plug-ins.  I would recommend changing this extension to something unique to your application and add that extension (or UTI) to your main application as an accepted file type.  See previous articles here on CIMGF to see how to do each of those.</p>

<p><center><a href="http://www.cimgf.com/wp-content/uploads/2008/09/frameworks.zip" title="Example Project"><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br/>Example Project</a></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/09/17/cocoa-tutorial-adding-plugins-to-a-cocoa-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Rendering QuickTime Movies In A CAOpenGLLayer</title>
		<link>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/</link>
		<comments>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 15:20:38 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Core Video]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[QTKit]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=219</guid>
		<description><![CDATA[I&#8217;ve been experimenting a great deal lately with OpenGL and QuickTime trying to see how the two technologies work together. It&#8217;s been a bit challenging, but fortunately Apple provides two really great resources&#8211;number one, sample code. I&#8217;ve been able to learn a lot just from the samples they provide in the development tools examples as [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been experimenting a great deal lately with OpenGL and QuickTime trying to see how the two technologies work together. It&#8217;s been a bit challenging, but fortunately Apple provides two really great resources&#8211;number one, sample code. I&#8217;ve been able to learn a lot just from the samples they provide in the development tools examples as well as online. And second, the cocoa-dev and quicktime-api lists are great. Lot&#8217;s of brilliant people there who are willing to share their knowledge. It&#8217;s very helpful, prohibition to discuss the iPhone SDK notwithstanding.</p>

<p>Getting two technologies to work together can be a challenge especially when the bridges between the two are not necessarily clearly laid out in documentation. As I pointed out Apple provides some excellent sample code to help you along, but there is no hand-holding approach to any of it. I actually appreciate that having come from the Windows world as it seems that there all you get sometimes is hand-holding where Microsoft doesn&#8217;t trust you, the developer to figure things out and really own what you&#8217;re doing. But I digress (wouldn&#8217;t be a CIMGF post if I didn&#8217;t dig on MS a bit).
<span id="more-219"></span></p>

<p>Like peanut butter and chocolate, what you get when you put together QuickTime and OpenGL is something greater than either of them left on their own (ok, this is subjective. Not everyone likes peanut butter and chocolate together, but again, I digress).</p>

<p>If you read the <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreVideo/CVProg_Intro/chapter_1_section_1.html">Core Video Programming Guide</a> from Apple, you see they provide the reasons for using Core Video:</p>

<blockquote>
CoreVideo is necessary only if you want to manipulate individual video frames. For example, the following types of video processing would require CoreVideo:
<ul>
<li>Color correction or other filtering, such as provided by Core Image filters 
<li>Physical transforms of the video images (such as warping, or mapping on to a surface) 
<li>Adding video to an OpenGL scene 
<li>Adding additional information to frames, such as a visible timecode 
<li>Compositing multiple video streams 
</ul>
</blockquote>

<p>If all you need to do is display a movie, you should simply use either a QTMovieView or, if you want to stick with the Core Animation route, use a QTMovieLayer. They both function similarly, however, the view provides a lot of features that you won&#8217;t have to implement in the UI yourself such as a scrubber or play/pause buttons. Plus the view is very fast and efficient. I&#8217;m in the process of exploring performance differences between the two, but I will save my comments about that for another post.</p>

<p>For our example code we are most interested in the third point above&#8211;<strong>adding video to an OpenGL scene</strong>. It seems that new QuickTime developers often want to know how to manipulate movie images before displaying them. Often this leads them to pursue adding sub-views to the movie view which can become a big mess. Because we are using OpenGL, doing other drawing on the scene is very fast. I won&#8217;t kid you. OpenGL is a pain. I don&#8217;t know anybody who loves it, but everybody respects it because of its raw speed.</p>

<p>Point number five above&#8211;<strong>compositing multiple video streams</strong>&#8211;is also interesting. While I won&#8217;t be covering it in this post, I will say that it makes a world of difference performance wise if you composite the movies into a OpenGL scene. If you&#8217;ve ever tried to run multiple videos simultaneously in two different views or layers, it can get pretty herky jerky. You can see why it is necessary to use OpenGL instead.</p>

<h2>The OpenGL QuickTime Two Step</h2>

<p>Ok, it actually will take more than two steps, however, when you are working with Core Animation layers things get a whole lot easier than they are for rendering a movie in an NSOpenGLView. Here is what you get for free, as the kids say.</p>

<ul>
<li>You don&#8217;t have to set up the OpenGL context. It is already available for you to send your OpenGL calls to.
<li>The viewport for display is already configured
<li>You don&#8217;t need to set up a display link callback
</ul>

<p>What took over 400 lines of code when rendering a QuickTime movie with no filters to an NSOpengGLView now only takes around 150 lines. Any time you can reduce code to something simpler, it makes life easier. It also makes it much easier to grok, in my opinion.</p>

<p>There really are two primary steps you take when using a CAOpenGLLayer. First you check to see if you should draw. Then, depending upon the answer, drawInCGLContext gets called or doesn&#8217;t. Really thats it. Determining whether or not you should draw depends upon what you are trying to do. In our case, we only want to draw if all of the following are true:</p>

<ul>
<li>The movie is actually playing back
<li>The visual context for the movie has been initialized
<li>The visual context has a new image ready to be rendered
</ul>

<p>If all of these are true, then our call to canDrawInCGLContext returns YES. Here is the code I use to check these contraints in canDrawInCGLContext:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>canDrawInCGLContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
                pixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat 
               forLayerTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CFTimeInterval<span style="color: #002200;">&#41;</span>timeInterval 
                displayTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> CVTimeStamp <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>timeStamp
<span style="color: #002200;">&#123;</span> 
    <span style="color: #11740a; font-style: italic;">// There is no point in trying to draw anything if our</span>
    <span style="color: #11740a; font-style: italic;">// movie is not playing.</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>movie rate<span style="color: #002200;">&#93;</span> &lt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span> <span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>qtVisualContext <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// If our visual context for our QTMovie has not been set up</span>
        <span style="color: #11740a; font-style: italic;">// we initialize it now</span>
        <span style="color: #002200;">&#91;</span>self setupVisualContext<span style="color: #002200;">:</span>glContext withPixelFormat<span style="color: #002200;">:</span>pixelFormat<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Check to see if a new frame (image) is ready to be draw at</span>
    <span style="color: #11740a; font-style: italic;">// the time specified.</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>QTVisualContextIsNewImageAvailable<span style="color: #002200;">&#40;</span>qtVisualContext,timeStamp<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Release the previous frame</span>
        CVOpenGLTextureRelease<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Copy the current frame into our image buffer</span>
        QTVisualContextCopyImageForTime<span style="color: #002200;">&#40;</span>qtVisualContext,
                                        <span style="color: #a61390;">NULL</span>,
                                        timeStamp,
                                        <span style="color: #002200;">&amp;</span>currentFrame<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Returns the texture coordinates for the part of the image that should be displayed</span>
        CVOpenGLTextureGetCleanTexCoords<span style="color: #002200;">&#40;</span>
                            currentFrame, 
                            lowerLeft, 
                            lowerRight, 
                            upperRight, upperLeft<span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The call to setup the visual context is where we are associating the QuickTime movie itself with a QTVisualContextRef object which is what OpenGL needs to draw the current frame. We will then use this object to load image data into a CVImageBufferRef which can be used for rendering with OpenGL. Here is the code to set up the visual context.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setupVisualContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
           withPixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat;
<span style="color: #002200;">&#123;</span>
    OSStatus			    error;
&nbsp;
    <span style="color: #400080;">NSDictionary</span>	    <span style="color: #002200;">*</span>attributes <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    attributes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">&#93;</span>,
                   kQTVisualContextTargetDimensions_WidthKey,
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">&#93;</span>,
                   kQTVisualContextTargetDimensions_HeightKey, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>, 
                  kQTVisualContextTargetDimensionsKey, 
                  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">&#93;</span>, 
                   kCVPixelBufferWidthKey, 
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">&#93;</span>, 
                   kCVPixelBufferHeightKey, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>, 
                  kQTVisualContextPixelBufferAttributesKey,
                  <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create our quicktimee visual context</span>
    error <span style="color: #002200;">=</span> QTOpenGLTextureContextCreate<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>,
                                         glContext,
                                         pixelFormat,
                                         <span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>attributes,
                                         <span style="color: #002200;">&amp;</span>qtVisualContext<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Associate it with our movie.</span>
    SetMovieVisualContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>movie quickTimeMovie<span style="color: #002200;">&#93;</span>,qtVisualContext<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Next we check to see if there is an image ready using:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>QTVisualContextIsNewImageAvailable<span style="color: #002200;">&#40;</span>qtVisualContext,timeStamp<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span></pre></td></tr></table></div>


<p>And then we copy the image to our CVImageBufferRef with:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Copy the current frame into our image buffer</span>
QTVisualContextCopyImageForTime<span style="color: #002200;">&#40;</span>qtVisualContext,
                                <span style="color: #a61390;">NULL</span>,
                                timeStamp,
                                <span style="color: #002200;">&amp;</span>currentFrame<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>Now it&#8217;s all a matter of rendering the frame for the current time stamp.</p>

<h2>But Wait! What TimeStamp?</h2>

<p>If you asked this question, then you are a very astute reader. In order to obtain the next image, we simply passed the CVTimeStamp parameter, <em>timeStamp</em> to our call to QTVisualContextCopyImageForTime. But how do we even have a timestamp? Isn&#8217;t that something we need to get from a display link? If you&#8217;re asking what is a display link at this point, take a look at the <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreVideo/CVProg_Concepts/chapter_2_section_3.html">Core Video Programming Guide</a> which states:</p>

<blockquote>
To simplify synchronization of video with a displayâ€™s refresh rate, Core Video provides a special timer called a display link. The display link runs as a separate high priority thread, which is not affected by interactions within your application process.

In the past, synchronizing your video frames with the displayâ€™s refresh rate was often a problem, especially if you also had audio. You could only make simple guesses for when to output a frame (by using a timer, for example), which didnâ€™t take into account possible latency from user interactions, CPU loading, window compositing and so on. The Core Video display link can make intelligent estimates for when a frame needs to be output, based on display type and latencies.
</blockquote>

<p>I will provide a more complete answer to the question in the future as I am still studying it myself, however, I will mention that a display link callback is unnecessary in this context as the CAOpenGLLayer is providing this for us. The timestamp field is all we need in order to get the current frame assuming that the movie is playing back.</p>

<h2>Drawing The Frame</h2>

<p>There is a special group of people who really get OpenGL. I salute all of you to whom this applies. You are amazing. I, however, only write as much of it as necessary and you&#8217;ll see that most of the code I have here is simply a copy and paste from sample code I got from Apple. I am starting to understand it more and more, however, it makes my brain hurt. Here is my drawing code for when a frame is ready to be rendered.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawInCGLContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
             pixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat 
            forLayerTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CFTimeInterval<span style="color: #002200;">&#41;</span>interval 
             displayTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> CVTimeStamp <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>timeStamp
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">NSRect</span>    bounds <span style="color: #002200;">=</span> NSRectFromCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    GLfloat 	minX, minY, maxX, maxY;        
&nbsp;
    minX <span style="color: #002200;">=</span> NSMinX<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    minY <span style="color: #002200;">=</span> NSMinY<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    maxX <span style="color: #002200;">=</span> NSMaxX<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    maxY <span style="color: #002200;">=</span> NSMaxY<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
&nbsp;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_MODELVIEW<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_PROJECTION<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glOrtho<span style="color: #002200;">&#40;</span> minX, maxX, minY, maxY, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    glClearColor<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span><span style="color: #002200;">&#41;</span>;	     
    glClear<span style="color: #002200;">&#40;</span>GL_COLOR_BUFFER_BIT<span style="color: #002200;">&#41;</span>;
&nbsp;
    CGRect imageRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Enable target for the current frame</span>
    glEnable<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">// Bind to the current frame</span>
    <span style="color: #11740a; font-style: italic;">// This tells OpenGL which texture we are wanting </span>
    <span style="color: #11740a; font-style: italic;">// to draw so that when we make our glTexCord and </span>
    <span style="color: #11740a; font-style: italic;">// glVertex calls, our current frame gets drawn</span>
    <span style="color: #11740a; font-style: italic;">// to the context.</span>
    glBindTexture<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>, 
                  CVOpenGLTextureGetName<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_TEXTURE<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glColor4f<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#41;</span>;
    glBegin<span style="color: #002200;">&#40;</span>GL_QUADS<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Draw the quads</span>
    glTexCoord2f<span style="color: #002200;">&#40;</span>upperLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, upperLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x, 
                 imageRect.origin.y <span style="color: #002200;">+</span> imageRect.size.height<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>upperRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, upperRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x <span style="color: #002200;">+</span> imageRect.size.width, 
                 imageRect.origin.y <span style="color: #002200;">+</span> imageRect.size.height<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>lowerRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, lowerRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x <span style="color: #002200;">+</span> imageRect.size.width, 
                 imageRect.origin.y<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>lowerLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, lowerLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x, imageRect.origin.y<span style="color: #002200;">&#41;</span>;
&nbsp;
    glEnd<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// This CAOpenGLLayer is responsible to flush</span>
    <span style="color: #11740a; font-style: italic;">// the OpenGL context so we call super</span>
    <span style="color: #002200;">&#91;</span>super drawInCGLContext<span style="color: #002200;">:</span>glContext 
                pixelFormat<span style="color: #002200;">:</span>pixelFormat 
               forLayerTime<span style="color: #002200;">:</span>interval 
                displayTime<span style="color: #002200;">:</span>timeStamp<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Task the context</span>
    QTVisualContextTask<span style="color: #002200;">&#40;</span>qtVisualContext<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>If you&#8217;re not familiar with OpenGL it would help you to know that it&#8217;s all about the current state. What does this mean? Well, simply put, it means that the call you are making right now, applies to whatever state the context is in. These two calls are what are the most important for our purposes.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">glEnable<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
glBindTexture<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>, 
                  CVOpenGLTextureGetName<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>With these two calls we have told OpenGL which texture to use. Now, every subsequent call applies to this texture until the state is changed to something else. So now, when we set a color or draw a quad, it applies to the texture that has been set here.</p>

<h2>Conclusion</h2>

<p>I love both of these technologies, QuickTime and OpenGL. They are so powerful. It&#8217;s harnessing the power that&#8217;s the trick. I&#8217;ve got some other ideas for some related posts that I plan to cover in the weeks to come, but this was a real breakthrough for me. With the help of John Clayton, Jean-Daniel Dupas, and David Duncan on the cocoa-dev list, I was able to get the sample code put together for this post. Feel free to ask questions in the comments. I will do my best to answer, but I&#8217;m still pretty new to these technologies. Write some code yourself and have fun. This is really exciting stuff. Until next time.</p>

<h2>About The Demo Code</h2>

<p><strike>John Clayton has some issues getting the code to work on his Mac Pro. I successfully ran it on  my MacBook Pro, and the family iMac without any issues. Anyhow, we&#8217;re not sure what the problem is, so if you do run into trouble, let me know. Maybe we can figure it out. Meanwhile we&#8217;re investigating it as we have time.</strike></p>

<p><strong>Update:</strong> John Clayton figured it out. Apparently the visual context needs to be reset because the pixel format is not correct on the first run. We just reset the visual context now in the call to -copyCGLContextForPixelFormat and everything seems happy. The demo code has been updated to reflect the change.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/09/qtglcalayerdemo.zip'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="Quicktime CAOpenGLLayer Demo" title="Quicktime CAOpenGLLayer Demo" width="64" class="aligncenter size-medium wp-image-49" /><br />Quicktime CAOpenGLLayer Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Sync Services without Core Data</title>
		<link>http://www.cimgf.com/2008/08/27/cocoa-tutorial-sync-services-without-core-data/</link>
		<comments>http://www.cimgf.com/2008/08/27/cocoa-tutorial-sync-services-without-core-data/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 22:23:23 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=216</guid>
		<description><![CDATA[Sync Services have come a long way in Leopard. Before Leopard it was an extremely complex operation that was almost completely manual. Needless to say, this sucked and it was probably one of the reasons it was shunned by most developers. If you are using Core Data in a Leopard application then Sync Services is [...]]]></description>
			<content:encoded><![CDATA[<p>Sync Services have come a long way in Leopard.  Before Leopard it was an extremely complex operation that was almost completely manual.  Needless to say, this sucked and it was probably one of the reasons it was shunned by most developers.</p>

<p>If you are using Core Data in a Leopard application then Sync Services is so trivial that you should be syncing if it makes sense.  In this article we are going to cover syncing in a non-Core Data situation as that is quite a bit more complex.</p>

<p>If you have read the Sync Services documentation then you know it is complex.  Let me dispel an illusion right away.  It is hard.  It is not poor documentation, syncing is very hard and very few people get it right.  Take a look at Omnifocus to see an example of a company thinking it is easy and losing data.  Therefore if you are expecting this subject to be trivial you will be disappointed.</p>

<p>In this example we will be syncing with the bookmarks schema and displaying them in a simple outline view.  The outline view itself will be editable and those edits can be synced back.  Not terribly useful but provides a very simple example.
<span id="more-216"></span></p>

<h2>Sync Services Setup</h2>

<p>There are a few different ways to implement sync services inside of your application.  You can set up a sync client and handle everything manually just like we did in Tiger but to be honest, unless you need Tiger compatibility, I would not use that approach again.  The option we are going to use in this article is new to Leopard and that will be employing a ISyncDriver.  The driver is basically a default sync client that handle some of the mess for us.  To create the driver, we need to pass it a data source:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">syncDriver <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ISyncSessionDriver sessionDriverWithDataSource<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span> retain<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>syncDriver setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>self setPreferredSyncMode<span style="color: #002200;">:</span>ISyncSessionDriverModeFast<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">SEL</span> syncSEL <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>client<span style="color: #002200;">:</span>willSyncEntityNames<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>syncDriver client<span style="color: #002200;">&#93;</span> setSyncAlertHandler<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span>syncSEL<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>syncDriver sync<span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>In our example application, we are going to hold on to a reference to the syncDriver object so that we can request syncs whenever it is appropriate.  To be a data source for the ISyncSessionDriver class, the object needs to implement the protocol ISyncSessionDriverDataSource.  While this protocol has a few optional methods, pretty much all of the methods in the protocol are required.  In the example application for this article, the application&#8217;s delegate is also the data source and the delegate.  I would not recommend this for a production application as it makes the application delegate pretty big; it is sufficient for this example.</p>

<p>Once the syncDriver has been initialized, I want to request a sync immediately on start up.  This makes sure that the application is dealing with fresh data as opposed to something that may have changed while the application was not running<sup>1</sup>.  Just before I call [syncDriver sync] though I do want to flag my object as the handler for sync alerts.  This is a callback method used by the sync engine to tell my application that a sync is occurring on data that I care about and it gives me the opportunity to be apart of that sync.  Once I have set myself up as a receiver for those alerts it is time to perform the first sync.</p>

<p>There are essentially three phases when your application is going to perform a sync.  Two of those phases our application will have a direct involvement with.  The first phase, called the push phase, is where we send our data to the Truth.  The Truth is a database that lives on each Mac and keeps track of all the data that is being synced.  The Truth handles all merging of data and each application can request a copy of data from it.</p>

<h3>Push</h3>

<div style="float: right;width: 19em;margin: 0 0 0 0.2em;padding-left: 0.2em;background: #FFFF00;">
    <strong>Entity Names</strong><br/>
    Entity names are similar to bundle identifiers in that they uniquely name a data object.  In this example we are syncing with the system bookmarks so our two entity names we are dealing with are com.apple.Bookmark and com.apple.Folder.
</div>

<p>In the first phase of a sync, we push our data to the Truth.  Since this example application does not retain any data this will be very quick.  The first part of this push, our application needs to list all of the data objects it knows about for each entity type.  The method that handles this is -recordsForEntityName: moreComing: error:.  This method returns a dictionary of all the data for a specific entity name.</p>

<p>In that NSDictionary, the key is the unique identifier for that record which is provided by the Truth.  The object is another NSDictionary with the properties of the object contained within.  In our example application, this method is implemented as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>recordsForEntityName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entityName 
                          moreComing<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>moreComing 
                               error<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">**</span><span style="color: #002200;">&#41;</span>outError
<span style="color: #002200;">&#123;</span>
	<span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>dict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionary<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>recordID <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">id</span> object <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self objectForRecordIdentifier<span style="color: #002200;">:</span>recordID<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>objectEntityName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>object class<span style="color: #002200;">&#93;</span> entityName<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>objectEntityName isEqualToString<span style="color: #002200;">:</span>entityName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #a61390;">continue</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#91;</span>dict setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>object fullRecord<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span>recordID<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
&nbsp;
  <span style="color: #002200;">*</span>moreComing <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
  <span style="color: #a61390;">return</span> dict;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>The more coming flag is used when an application wants to send the data in batches.  If it is set to YES then the method will be called repeatedly with the same entityName until a NO is received.  <strong>NOTE:</strong>This method is normally only called on the first sync.</p>

<p>Once our application had told the Truth about all of the data it knows about, the next part of the push phase is to send any changes that have occurred since the last sync.  This is handled in one of two methods.  If our application can accurately describe each property that has changed then the -changesForEntityName: moreComing: error: method can be used.  If, however, we only know that an object has changed but not which specific properties, then the -changedRecordsForEntityName:moreComing:error: method would be used.  The former method is easier on the sync since it does not need to resolve that information itself.  In our implementation we will be using the latter implementation to make our lives easier.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>changedRecordsForEntityName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entityName 
                                 moreComing<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>moreComing 
                                      error<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">**</span><span style="color: #002200;">&#41;</span>outError
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>dict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionary<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>key <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">id</span> object <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> objectForKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>object updated<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">continue</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>object entityName<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span>entityName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">continue</span>;
    <span style="color: #002200;">&#91;</span>dict setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>object fullRecord<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #a61390;">return</span> dict;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Here we are looping through all of our objects (we store them in a NSDictionary as well to make life easier in the demo) and if an object has the right entity name as well as being flagged as updated we send its data back.  Again, we can set the moreComing flag to YES if we need to handle the data in batches.</p>

<h3>Mingle</h3>

<p>Once we have pushed our data and our changes up to the server and all of the other participants of this sync session have done the same, the Truth mingles the data.  It will do its best to merge everything and if it fails it will ask the user to decide which change is the correct one.</p>

<p>Clients have no participation in this phase of the sync session.  Once the mingle is complete the next phase is started automatically by the ISyncSessionDriver.</p>

<h3>Push</h3>

<p>Once the data has been mingled, the Truth will then inform each client of any changes that have taken place.  It is expected that each client will accept these changes and store them in their local data stores.  The method that is called is -applyChange:forEntityName:remappedRecordIdentifier:formattedRecord:error:.  This method will be called for each entity that has changed as a result of the mingle so it needs to be as efficient as possible.</p>

<p>When this method is called, a ISyncChange object is passed in.  This object contains all of the information about the change that needs to be performed.  The first thing that needs to be looked at is what type of change it is.  A change can be a new record, deleting an existing record or updating a record.  Our implementation of this method is as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span>ISyncSessionDriverChangeResult<span style="color: #002200;">&#41;</span>applyChange<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>ISyncChange<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>change 
                                forEntityName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>entityName 
                     remappedRecordIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">**</span><span style="color: #002200;">&#41;</span>outRecordIdentifier 
                              formattedRecord<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span><span style="color: #002200;">**</span><span style="color: #002200;">&#41;</span>outRecord 
                                        error<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">**</span><span style="color: #002200;">&#41;</span>err
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>errDict <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #a61390;">id</span> record <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #a61390;">switch</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>change type<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">case</span> ISyncChangeTypeDelete<span style="color: #002200;">:</span>
      <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> removeObjectForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>change recordIdentifier<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
      <span style="color: #a61390;">return</span> ISyncSessionDriverChangeAccepted;
    <span style="color: #a61390;">case</span> ISyncChangeTypeAdd<span style="color: #002200;">:</span>
      <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>entityName isEqualToString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>FolderEntity entityName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        record <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>FolderEntity alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>entityName isEqualToString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>BookmarkEntity entityName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        record <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>BookmarkEntity alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        errDict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unknown type&quot;</span>
                                              forKey<span style="color: #002200;">:</span>NSLocalizedDescriptionKey<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">*</span>err <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSError</span> errorWithDomain<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CIMGF&quot;</span> code<span style="color: #002200;">:</span><span style="color: #2400d9;">8002</span> userInfo<span style="color: #002200;">:</span>errDict<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span> ISyncSessionDriverChangeError;
      <span style="color: #002200;">&#125;</span>
      <span style="color: #002200;">&#91;</span>record setRecordIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>change recordIdentifier<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> setObject<span style="color: #002200;">:</span>record forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>change recordIdentifier<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
      <span style="color: #a61390;">break</span>;
    <span style="color: #a61390;">case</span> ISyncChangeTypeModify<span style="color: #002200;">:</span>
      record <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self recordLookup<span style="color: #002200;">&#93;</span> objectForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>change recordIdentifier<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
      <span style="color: #a61390;">break</span>;
    <span style="color: #a61390;">default</span><span style="color: #002200;">:</span>
      errDict <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unknown type&quot;</span>
                                            forKey<span style="color: #002200;">:</span>NSLocalizedDescriptionKey<span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">*</span>err <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSError</span> errorWithDomain<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CIMGF&quot;</span> code<span style="color: #002200;">:</span><span style="color: #2400d9;">8001</span> userInfo<span style="color: #002200;">:</span>errDict<span style="color: #002200;">&#93;</span>;
      <span style="color: #a61390;">return</span> ISyncSessionDriverChangeError;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>changeDict <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span>change changes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>action <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>changeDict valueForKey<span style="color: #002200;">:</span>ISyncChangePropertyActionKey<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>name <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>changeDict valueForKey<span style="color: #002200;">:</span>ISyncChangePropertyNameKey<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>name isEqualToString<span style="color: #002200;">:</span>kRecordEntityName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #a61390;">continue</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>action isEqualToString<span style="color: #002200;">:</span>ISyncChangePropertyClear<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>record setNilValueForKey<span style="color: #002200;">:</span>name<span style="color: #002200;">&#93;</span>;
      <span style="color: #a61390;">continue</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">id</span> value <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>changeDict valueForKey<span style="color: #002200;">:</span>ISyncChangePropertyValueKey<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>record setValue<span style="color: #002200;">:</span>value forKey<span style="color: #002200;">:</span>name<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#91;</span>record setUpdated<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">return</span> ISyncSessionDriverChangeAccepted;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>In this method we use a switch to determine what type of change that it is.  If it is a delete we remove the record from our global store and return happy.  If it is an add then we create a new empty object and set the recordIdentifier.  Lastly, if it is a change we retrieve the record from our global store.</p>

<p>Once the object that is going to be changed has been referenced we loop through the changes which are stored in an array inside of the ISyncChange object.  Each object in the array is a dictionary containing up three values.  The first value has a key of ISyncChangePropertyActionKey and the value can either be ISyncChangePropertySet or ISyncChangePropertyClear.  If it is a clear then we are to set the property to nil.  Otherwise we change the property to the value stored under key ISyncChangePropertyValueKey.  The name of the property is stored under the key ISyncChangePropertyNameKey.  If our properties use the same name as the sync objects they represent (and in our case they do) then this step is performed in a loop using KVC to update each property.</p>

<p>Once we have updated the object we return ISyncSessionDriverChangeAccepted to let the sync engine know that everything is happy.  We could have returned ISyncSessionDriverChangeIgnored or ISyncSessionDriverChangeRejected if we did not accept the change for some reason.  In either of those cases the object and its changes would not be sent to us again unless it changed in the future.  Lastly, if there is a problem, we can return ISyncSessionDriverChangeError if there was an error.  If we return that, however, the sync engine expects us to populate the NSError pointer before returning.</p>

<p>There are two other pointers that get passed in that should be mentioned.  The first one, called outRecordIdentifier in this example is used in the case where we do not want to use the recordIdentifier being passed to us.  Perhaps we have our own internal schema or we want to reference this record by another identifier.  If we set this pointer then the Truth will remember that change and use the new identifier in the future when talking to us.  It will not use this new identifier when talking to anyone else though.  This is useful when syncing with a database that uses something other than a guid for uniqueness.  The second one, called outRecord in this example, is used to update the object.  Perhaps we had a field on new records or change a field; in either case those changes can be sent back to the Truth via this pointer.</p>

<h3>Other Data Source methods</h3>

<p>That is the major points of a sync.  We of course have a lot more flexibility to cover edge cases and we can make changes at any step in the process via the delegate methods but those are the points of contact for passing data back and forth.  Other than those complicated touch points, there are a few other methods that need to be implemented to make a sync work.  Those methods are more administrative and far less complicated.</p>

<ul>
  <li>clientIdentifier<br/>
    This is the unique string that identifies this client to the Truth.  I like to use the bundle identifier here just to make things simple.</li>
  <li>schemaBundleURLs<br/>
    This method returns an array of NSURL objects.  Each NSURL object points to a schema either on disk or on the net that describes the data to be stored in the Truth.  If we are creating a new set of data then we would need to generate a schema (and there is a template in Xcode for that purpose).  If not then we need to reference the existing schema.</li>
  <li>entityNamesToSync<br/>It is not necessary to sync every entity in a schema (although in our case we do since there are only two).  If we only care about a subset of the data then we can request to sync only those entities we care about.  In any case we pass back an array of strings here to let the sync engine know which entities we care about.</li>
  <li>preferredSyncModeForEntityName<br/>A fast sync is always the goal.  However if we need to refresh an object or perform a slow sync (useful when a large amount of data has changed or we lost our copy of the data) then this is the method that determines it.  This method will be called once for each entity we want to sync.</li>
  <li>clientDescriptionURL<br/>The client description is a plist file that describes this client to the sync engine.  For example, the icon used in dialogs is defined in this plist along with the human readable name of the sync client, etc.  Also in this plist we define what properties of each entity we want synced.  If we only want a subset of the entities we can control that here.</li>
</ul>

<h3>Conclusion</h3>

<p>I would not be at all surprised if that was as clear as mud.  The sync services framework is complicated, no doubt about that.  That complication has a purpose though, it is incredibility powerful as well.  Now that I have scratched the surface in this article I will be adding other articles to explain some of the more complicated aspects such as adding properties to an existing schema, mid-sync data changing and more.</p>

<p>If a part of this is unclear, please post a comment and I will update it to help clarify.  I would also recommend downloading the example application that is attached as I find the code much easier to understand.</p>

<p><center></p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2008/08/syncservicestutoral1.zip" title="Sync Services Tutorial 1"><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br/>Sync Services Tutorial 1</a></a></p>

<p></center></p>

<p><small>1. There is an option to have a helper tool that sync services will run when your application is not running but that is beyond the scope of this article.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/08/27/cocoa-tutorial-sync-services-without-core-data/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: libxml and xmlreader</title>
		<link>http://www.cimgf.com/2008/08/18/cocoa-tutorial-libxml-and-xmlreader/</link>
		<comments>http://www.cimgf.com/2008/08/18/cocoa-tutorial-libxml-and-xmlreader/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 01:49:24 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=198</guid>
		<description><![CDATA[Let us pretend for a moment that NSXMLDocument was not available to your Cocoa application for some reason. Perhaps you have low memory requirements, perhaps you are running on a slimmed down version of OS X. Whatever the reason, for the purposes of this exercise, NSXMLDocument does not exist. Let us now assume that we [...]]]></description>
			<content:encoded><![CDATA[<p>Let us pretend for a moment that NSXMLDocument was not available to your Cocoa application for some reason. Perhaps you have low memory requirements, perhaps you are running on a slimmed down version of OS X.  Whatever the reason, for the purposes of this exercise, NSXMLDocument does not exist.</p>

<p>Let us now assume that we have a requirement to parse an xml document quickly and without loading the entire tree into memory in a object structure.  In a situation like this libxml comes in handy.  Unfortunately it is quite a bit more complicated than calling alloc init on NSXMLDocument.</p>

<p>libxml is a C library that is included with all current releases of OS X.  With this library we can quickly read in a document, scrape the information we need out of that document and avoid loading the entire tree into memory at once.  In addition, libxml (and more specifically xmlReader) does this very quickly, far faster than NSXMLDocument which is very useful when you have a lower end CPU.  In this project we are going to create a simple application that reads in an xml file containing a list of people, their names and their ages.  For the purposes of demonstration we are going to load that data into an array of NSDictionary objects and display it in a standard Cocoa window.</p>

<p><span id="more-198"></span></p>

<p>The raw XML file looks like this:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;root<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>John Doe<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>14<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mary Doe<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>14<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>John Smith<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>14<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/person<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/root<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Besides being a C library, another difference in the way that we are going to read in this xml file is that the reading is iterative.  For each element in the xml file we will be looping over the reader.  Therefore, unlike our old friend NSXMLDocument, we will have to actually walk the file one element at a time and evaluate those elements as we receive them.  In the xml file listed above, we would first read in the opening root tag, then the opening person tag, the opening name tag, the first name, etc. until we were done with the file.</p>

<p>To accomplish our goal, I created a new Xcode project which can be downloaded below.  In this Xcode project, I added the libxml &#8220;framework&#8221; to the project by right clicking on the target, clicking on the add button, narrowing the focus to libraries and selecting the libxml2.dylib file.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/08/addlibxml2.tif' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/08/addlibxml2.tif" alt="Addlibxml2.tif" border="0" width="25%"/></a></p>

<p>This will link libxml to our project at compile time.  However, unlike an Objective-C framework, we do not get access to its headers for free.  Therefore the next step is to add the header to our search path.  To do so, open the target&#8217;s properties and select the build tab.  Narrow its focus to &#8220;header&#8221; and select the header search path entry.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/08/addheadersearchpath.tif' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/08/addheadersearchpath.tif" alt="AddHeaderSearchPath.tif" border="0" width="25%"/></a></p>

<p>Double click on this row and add /usr/include/libxml to the list of paths.  NOTE: Some people have had issues with this path and if you do then you will need to find another copy of these headers in your Xcode installation directory.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/08/thepathtoadd.tif' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/08/thepathtoadd.tif" alt="ThePathToAdd.tif" border="0" width="25%"/></a></p>

<p>Once this is done, we will be able to compile against this library with no errors or warnings.  Next, after we add an application delegate and wire it up in our xib file, we need to import libxml in our AppDelegate.h.  While we are in here we are going to add a reference for our records array that we will be loading the data into.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
<span style="color: #6e371a;">#include &lt;libxml/xmlreader.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> AppDelegate <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>_records;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>retain<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>records;
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>


<p>Since xmlReader is so quick, our data set is so small and this is a demonstration only, we are going to read the xml file directly as the application starts.  <strong>BE WARNED:</strong> for a production application <strong><emph>THIS IS A BAD IDEA</emph></strong><sup>tm</sup>.  Fortunately I can get away with a lot in demos. :-)</p>

<p>The first thing we need to do in the -applicationDidFinishLaunching: method is to load the xml data and initialize the xml reader.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;xmlExample&quot;</span> ofType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;xml&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>xmlData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithContentsOfFile<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;
  xmlTextReaderPtr reader <span style="color: #002200;">=</span> xmlReaderForMemory<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>xmlData bytes<span style="color: #002200;">&#93;</span>, 
                                               <span style="color: #002200;">&#91;</span>xmlData length<span style="color: #002200;">&#93;</span>, 
                                               <span style="color: #002200;">&#91;</span>path UTF8String<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">nil</span>, 
    <span style="color: #002200;">&#40;</span>XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>reader<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to load xmlreader&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span>;
  <span style="color: #002200;">&#125;</span></pre></div></div>


<p>In this section, again for demonstration purposes, we are reading in the included xml file into an NSData object.  Normally we would be retrieving this data from an NSURLConnection or some other external source.  Once the data is loaded, we pass the raw bytes off to the C function xmlReaderForMemory().  This function will return a pointer reference to our xmlReader.  This reader is now ready to walk, one way and one time, through our xml file.  Now we need to declare some local variables to store our state information while we walk the xml file.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>currentTagName <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>currentPerson <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>currentTagValue <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>people <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">true</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>xmlTextReaderRead<span style="color: #002200;">&#40;</span>reader<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">break</span>;
    <span style="color: #a61390;">switch</span> <span style="color: #002200;">&#40;</span>xmlTextReaderNodeType<span style="color: #002200;">&#40;</span>reader<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span></pre></div></div>


<p>Since this xml file is very simple we do not need to hold onto a lot of state information.  Basically when we hit a person tag we will create a new person dictionary and then every time we hit a text node we will store that text node&#8217;s value into the dictionary along with the tag name.  Finally we will store each of those person dictionaries into an array.</p>

<p>Once our variables are declared and initialized it is time to start walking the xml file.  Since we do not know how long it is going to be we will simply loop until we hit the end.  Therefore we have a while(true) to start the loop.  The first thing we do inside of the loop is to tell the reader to read the next element.  If that returns back a 0 we are done with the file and break.  If it returns back a positive value then we know the reader has advanced to the next node.  Since the node types are stored as integer values, we can use a switch statement to quickly sort them as we are looping.  The xmlTextReaderNodeType() function will return that type integer.</p>

<p>For our purposes, we really only care about two of the node types, opening tags and text values.  For a more complex xml file we would watch for more information but fortunately we are working in a controlled environment.  The tags we are going to watch for are XML_READER_TYPE_ELEMENT and XML_READER_TYPE_TEXT.</p>

<p>When we hit an element we will grab its name, store it temporarily and check to see if it is a person, if it isn&#8217;t then we loop.  If it is then we create a person and add it to our array.</p>

<p>When we hit a text node then we want to stick it in the current person object.  Since we previously stored the name of this element (remember, an element and its text value are two separate nodes), we can grab the value of the text and store it in the dictionary.</p>

<p>Any other type of node is ignored and we continue on the default: tag of the switch.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">case</span> XML_READER_TYPE_ELEMENT<span style="color: #002200;">:</span>
  <span style="color: #11740a; font-style: italic;">//We are starting an element</span>
  temp <span style="color: #002200;">=</span>  <span style="color: #002200;">&#40;</span><span style="color: #a61390;">char</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>xmlTextReaderConstName<span style="color: #002200;">&#40;</span>reader<span style="color: #002200;">&#41;</span>;
  currentTagName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithCString<span style="color: #002200;">:</span>temp 
                                      encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>currentTagName isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;person&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    currentPerson <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionary<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>people addObject<span style="color: #002200;">:</span>currentPerson<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span> 
  <span style="color: #a61390;">continue</span>;
<span style="color: #a61390;">case</span> XML_READER_TYPE_TEXT<span style="color: #002200;">:</span>
  <span style="color: #11740a; font-style: italic;">//The current tag has a text value, stick it into the current person</span>
  temp <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">char</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>xmlTextReaderConstValue<span style="color: #002200;">&#40;</span>reader<span style="color: #002200;">&#41;</span>;
  currentTagValue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithCString<span style="color: #002200;">:</span>temp 
                                       encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>currentPerson<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span>;
  <span style="color: #002200;">&#91;</span>currentPerson setValue<span style="color: #002200;">:</span>currentTagValue forKey<span style="color: #002200;">:</span>currentTagName<span style="color: #002200;">&#93;</span>;
  currentTagValue <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
  currentTagName <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #a61390;">default</span><span style="color: #002200;">:</span> <span style="color: #a61390;">continue</span>;</pre></div></div>


<p><a href='http://www.cimgf.com/wp-content/uploads/2008/08/finalwindow.tif' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/08/finalwindow.tif" alt="FinalWindow.tif" border="0" width="25%" style="float:right;padding: 2px 2px 2px 2px;"/></a>Since we check for the completion of the file a the beginning of the loop that is all that we need to do for this example.  Once the while loop exits we pass the array to -setRecords: and we are done.  Cocoa bindings will take care of the rest for us.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2008/08/xmlreaderexample.zip" title="XMLReaderExample.zip"><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br/>NSError Tutorial</a></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/08/18/cocoa-tutorial-libxml-and-xmlreader/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Custom Folder Icons</title>
		<link>http://www.cimgf.com/2008/06/16/cocoa-tutorial-custom-folder-icons/</link>
		<comments>http://www.cimgf.com/2008/06/16/cocoa-tutorial-custom-folder-icons/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 20:15:02 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[System Programming]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=132</guid>
		<description><![CDATA[This is just another one of those things that seems like it ought to be a simple little code snippet and you&#8217;re there, but in actuality it&#8217;s just not the case. I am building an exporter for my application that will export a movie project in iMovie HD format. I want to mimic the file [...]]]></description>
			<content:encoded><![CDATA[<p>This is just another one of those things that seems like it ought to be a simple little code snippet and you&#8217;re there, but in actuality it&#8217;s just not the case. I am building an exporter for my application that will export a movie project in <em>iMovie HD</em> format. I want to mimic the file format exactly and one of the things I noticed about the directories that are stored inside <em>iMovie HD</em>&#8216;s custom format (select &#8216;Show Package Contents&#8217; from the context menu in the <em>Finder</em>) is that they have custom icons assigned to them. So the problem to solve was how to do that programatically. Here is what I&#8217;ve found.
<span id="more-132"></span>
<strong style="color: red;">Stop The Presses</strong> After I published this yesterday, one of our kind readers pointed out in the comments that this problem has been solved much more elegantly using <em>NSWorkspace</em> starting in OS X Tiger (10.4). Yes. You read that right. Tiger! Heck if I could find this solution using Google, though. Oh well.. All you really need is <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/Reference/Reference.html#//apple_ref/occ/instm/NSWorkspace/setIcon:forFile:options:">- (BOOL)setIcon:(NSImage *)image forFile:(NSString *)fullPath options:(NSWorkspaceIconCreationOptions)options</a>  in <em>NSWorkspace</em> to do the same thing.</p>

<p>Feel free to read on as this will provide good legacy information. Just note that setting a custom icon for a folder is not as hard as this post would make it seem.</p>

<h2>Poking A Stick At It</h2>

<p>If you haven&#8217;t yet realized in your programming career that often the best and sometimes only way to figure something out is to &#8216;poke a stick at it&#8217; then it&#8217;s probably time you started. I&#8217;m not sure where this reference comes from, but it seems apropo. Maybe it&#8217;s a cave man thing? You&#8217;re not sure what something is, so you poke a stick at it and see what happens.</p>

<p>Different from cave men, though, my proverbial/virtual stick is <em>Terminal.app</em>. If you look inside an <em>iMovie HD</em> project file, which contains folders with custom icons, using <em>Terminal.app</em> you&#8217;ll see a listing that looks something like this.</p>

<p><pre>
drwxr-xr-x@  6 mlong  staff   204 Mar 17 18:00 Cache
-rw-r--r--@  1 mlong  staff  1677 Mar  7 17:22 Makin Guacamole.iMovieProj
-rw-r--r--@  1 mlong  staff   895 Mar  7 17:19 Makin Guacamole~.iMovieProj
drwxr-xr-x@  4 mlong  staff   136 Mar 17 18:00 Media
drwxr-xr-x@  5 mlong  staff   170 Mar  7 17:22 Shared Movies
</pre></p>

<p>This is a list from a time lapse movie I made of myself making guacamole. You can <a href="http://www.youtube.com/watch?v=51jomaA7S4Q">watch it here if you&#8217;re so inclined</a>. Notice that there are special attributes on each of the files and folders as indicated by the at (@) symbol. You can see what&#8217;s going on with a particular directory by using the <em>mdls</em> command. Try it on one of the folders, say <em>Media</em> for example. and you&#8217;ll get a listing like this.</p>

<p><pre>
bash: mlong$ mdls Media
kMDItemFSContentChangeDate = 2008-03-17 18:00:49 -0600
kMDItemFSCreationDate      = 2008-03-07 17:19:34 -0700
kMDItemFSCreatorCode       = ""
kMDItemFSFinderFlags       = 1024
kMDItemFSHasCustomIcon     = 1
kMDItemFSInvisible         = 0
kMDItemFSIsExtensionHidden = 0
kMDItemFSIsStationery      = 0
kMDItemFSLabel             = 0
kMDItemFSName              = "Media"
kMDItemFSNodeCount         = 2
kMDItemFSOwnerGroupID      = 20
kMDItemFSOwnerUserID       = 501
kMDItemFSSize              = (null)
kMDItemFSTypeCode          = ""
</pre></p>

<p>Notice that the attribute called <em> kMDItemFSHasCustomIcon</em> is set to 1. If you now <em>cd</em> into the <em>Media</em> directory and run <em>ls -al</em>. You&#8217;ll see something like the following.</p>

<p><pre>
bash: mlong$ ls -al
total 31480
drwxr-xr-x@ 4 mlong  staff       136 Mar 17 18:00 .
drwxr-xr-x@ 7 mlong  staff       238 Mar  7 17:22 ..
-rw-r--r--@ 1 mlong  staff         0 Mar 17 18:00 Icon?
-rw-r--r--@ 1 mlong  staff  16056849 Mar  7 17:20 Makin Guacamole 01.mov
</pre></p>

<p>See that little 0 byte file called <em>Icon?</em>. This is what is telling the Finder about the custom icon being used.</p>

<p>The next step now that I knew that there was actually a way to specify a custom icon was to do a Google search to see if anyone had provided code to use. It was pretty sparse, but I was able to find something useful which is what this post is really about. A company called Shiny Frog based in Italy posted some open-source code that demonstrates how to set custom folder icons among other things. <a href="http://www.shinyfrog.net/en/openSource/">You can download their entire open-source code base here</a>. I&#8217;ve leveraged only the folder icon setting code for this blog post.</p>

<h2>Coding It Up</h2>

<p>Here are the two projects for this post:
<a href='http://www.cimgf.com/wp-content/uploads/2008/06/setcustomiconprocedural.zip'>Set Custom Icon Project (Procedural Code)</a>
<a href='http://www.cimgf.com/wp-content/uploads/2008/06/setcustomicon.zip'>Set Custom Icon Project (OO Code)</a></p>

<p>In the end, this post is not so much a tutorial as it is a showcase of the code. The code that it takes to change a folder icon is fairly lengthy. I have broken it out into two projects here. In the first, I broke out the code from the class that it was in when I downloaded it from Shiny Frog and put it into a procedural format. The second uses the classes as they&#8217;re found in the Shiny Frog code. Here is the code for the procedural way in its entirety. I&#8217;ve left all of the original comments from Shiny Frog in the code.</p>

<blockquote><strong>Note:</strong> If you want to simply use the code as classes, stick around for the next section in this post as I explain how you can just use what Shiny Frog provided.</blockquote>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setIcon<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>iconFilepath forDirectory<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>directoryPath;
<span style="color: #002200;">&#123;</span>
&nbsp;
    FSRef ref;
    OSStatus result;
    IconFamilyHandle hIconFamily;
&nbsp;
    CFURLRef urlRef;
    Boolean gotFSRef;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create a CFURL with the specified POSIX path.</span>
    urlRef <span style="color: #002200;">=</span> CFURLCreateWithFileSystemPath<span style="color: #002200;">&#40;</span> kCFAllocatorDefault,
                                           <span style="color: #002200;">&#40;</span>CFStringRef<span style="color: #002200;">&#41;</span> iconFilepath,
                                           kCFURLPOSIXPathStyle,
                                           FALSE <span style="color: #11740a; font-style: italic;">/* isDirectory */</span> <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>urlRef <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't make a CFURLRef for the file.&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Try to create an FSRef from the URL.  (If the specified file doesn't exist, this</span>
    <span style="color: #11740a; font-style: italic;">// function will return false, but if we've reached this code we've already insured</span>
    <span style="color: #11740a; font-style: italic;">// that the file exists.)</span>
    gotFSRef <span style="color: #002200;">=</span> CFURLGetFSRef<span style="color: #002200;">&#40;</span> urlRef, <span style="color: #002200;">&amp;</span>ref <span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span> urlRef <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>gotFSRef<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't get an FSRef for the file.<span style="color: #2400d9;">\n</span>&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
    result <span style="color: #002200;">=</span> ReadIconFromFSRef<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>ref, <span style="color: #002200;">&amp;</span>hIconFamily <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self setAsCustomIconForDirectory<span style="color: #002200;">:</span>directoryPath familyHandle<span style="color: #002200;">:</span>hIconFamily<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> setAsCustomIconForDirectory<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>path familyHandle<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>IconFamilyHandle<span style="color: #002200;">&#41;</span>hIconFam;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSFileManager</span> <span style="color: #002200;">*</span>fm <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFileManager</span> defaultManager<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">BOOL</span> isDir;
    <span style="color: #a61390;">BOOL</span> exists;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>iconrPath;
    FSRef targetFolderFSRef, iconrFSRef;
    SInt16 file;
    OSErr result;
    <span style="color: #a61390;">struct</span> HFSUniStr255 filename;
    <span style="color: #a61390;">struct</span> FSCatalogInfo catInfo;
    Handle hExistingCustomIcon;
    IconFamilyHandle hIconFamily;
    Handle hIconFamilyCopy;
&nbsp;
    hIconFamily <span style="color: #002200;">=</span> hIconFam;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Confirm that &quot;path&quot; exists and specifies a directory.</span>
    exists <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>fm fileExistsAtPath<span style="color: #002200;">:</span>path isDirectory<span style="color: #002200;">:&amp;</span>isDir<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>isDir || <span style="color: #002200;">!</span>exists <span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Get an FSRef for the folder.</span>
&nbsp;
    CFURLRef urlRef;
    Boolean gotFSRef;
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create a CFURL with the specified POSIX path.</span>
    urlRef <span style="color: #002200;">=</span> CFURLCreateWithFileSystemPath<span style="color: #002200;">&#40;</span> kCFAllocatorDefault,
                                           <span style="color: #002200;">&#40;</span>CFStringRef<span style="color: #002200;">&#41;</span> path,
                                           kCFURLPOSIXPathStyle,
                                           FALSE <span style="color: #11740a; font-style: italic;">/* isDirectory */</span> <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>urlRef <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't make a CFURLRef for the file.&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Try to create an FSRef from the URL.  (If the specified file doesn't exist, this</span>
    <span style="color: #11740a; font-style: italic;">// function will return false, but if we've reached this code we've already insured</span>
    <span style="color: #11740a; font-style: italic;">// that the file exists.)</span>
    gotFSRef <span style="color: #002200;">=</span> CFURLGetFSRef<span style="color: #002200;">&#40;</span> urlRef, <span style="color: #002200;">&amp;</span>targetFolderFSRef <span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span> urlRef <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>gotFSRef<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't get an FSRef for the file.&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Remove and re-create any existing &quot;Icon\r&quot; file in the directory, and get an FSRef for it.</span>
    iconrPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>path stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Icon<span style="color: #2400d9;">\r</span>&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>fm fileExistsAtPath<span style="color: #002200;">:</span>iconrPath<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>fm removeFileAtPath<span style="color: #002200;">:</span>iconrPath handler<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>
            <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span> writeToFile<span style="color: #002200;">:</span>iconrPath atomically<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create a CFURL with the specified POSIX path.</span>
    urlRef <span style="color: #002200;">=</span> CFURLCreateWithFileSystemPath<span style="color: #002200;">&#40;</span> kCFAllocatorDefault,
                                           <span style="color: #002200;">&#40;</span>CFStringRef<span style="color: #002200;">&#41;</span> iconrPath,
                                           kCFURLPOSIXPathStyle,
                                           FALSE <span style="color: #11740a; font-style: italic;">/* isDirectory */</span> <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>urlRef <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't make a CFURLRef for the file.&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Try to create an FSRef from the URL.  (If the specified file doesn't exist, this</span>
    <span style="color: #11740a; font-style: italic;">// function will return false, but if we've reached this code we've already insured</span>
    <span style="color: #11740a; font-style: italic;">// that the file exists.)</span>
    gotFSRef <span style="color: #002200;">=</span> CFURLGetFSRef<span style="color: #002200;">&#40;</span> urlRef, <span style="color: #002200;">&amp;</span>iconrFSRef <span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span> urlRef <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>gotFSRef<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;** Couldn't get an FSRef for the file.<span style="color: #2400d9;">\n</span>&quot;</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Get type and creator information for the Icon file.</span>
    result <span style="color: #002200;">=</span> FSGetCatalogInfo<span style="color: #002200;">&#40;</span>
                              <span style="color: #002200;">&amp;</span>iconrFSRef,
                              kFSCatInfoFinderInfo,
                              <span style="color: #002200;">&amp;</span>catInfo,
                              <span style="color: #11740a; font-style: italic;">/*outName*/</span> <span style="color: #a61390;">NULL</span>,
                              <span style="color: #11740a; font-style: italic;">/*fsSpec*/</span> <span style="color: #a61390;">NULL</span>,
                              <span style="color: #11740a; font-style: italic;">/*parentRef*/</span> <span style="color: #a61390;">NULL</span> <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> result <span style="color: #002200;">==</span> fnfErr <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// The file doesn't exist. Prepare to create it.</span>
&nbsp;
        <span style="color: #a61390;">struct</span> FileInfo <span style="color: #002200;">*</span>finderInfo <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> FileInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>catInfo.finderInfo;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// These are the file type and creator given to Icon files created by</span>
        <span style="color: #11740a; font-style: italic;">// the Finder.</span>
        finderInfo<span style="color: #002200;">-</span>&gt;fileType <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">'icon'</span>;
        finderInfo<span style="color: #002200;">-</span>&gt;fileCreator <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">'MACS'</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Icon files should be invisible.</span>
        finderInfo<span style="color: #002200;">-</span>&gt;finderFlags <span style="color: #002200;">=</span> kIsInvisible;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Because the inited flag is not set in finderFlags above, the Finder</span>
        <span style="color: #11740a; font-style: italic;">// will ignore the location, unless it's in the 'magic rectangle' of</span>
        <span style="color: #11740a; font-style: italic;">// { -24,000, -24,000, -16,000, -16,000 } (technote TB42).</span>
        <span style="color: #11740a; font-style: italic;">// So we need to make sure to set this to zero anyway, so that the</span>
        <span style="color: #11740a; font-style: italic;">// Finder will position it automatically. If the user makes the Icon</span>
        <span style="color: #11740a; font-style: italic;">// file visible for any reason, we don't want it to be positioned in an</span>
        <span style="color: #11740a; font-style: italic;">// exotic corner of the window.</span>
        finderInfo<span style="color: #002200;">-</span>&gt;location.h <span style="color: #002200;">=</span> finderInfo<span style="color: #002200;">-</span>&gt;location.v <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Standard reserved-field practice.</span>
        finderInfo<span style="color: #002200;">-</span>&gt;reservedField <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Modified by Matteo Rattotti on: Wed Dec  5 14:56:52 2007</span>
        <span style="color: #11740a; font-style: italic;">// the catalog must be set</span>
        FSSetCatalogInfo <span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>iconrFSRef, kFSCatInfoFinderInfo, <span style="color: #002200;">&amp;</span>catInfo<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
		<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> result <span style="color: #002200;">!=</span> noErr <span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
			<span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
		<span style="color: #002200;">&#125;</span>
		<span style="color: #a61390;">else</span><span style="color: #002200;">&#123;</span> <span style="color: #11740a; font-style: italic;">// Modified by Matteo Rattotti on: Wed Dec  5 14:56:52 2007</span>
			<span style="color: #11740a; font-style: italic;">// File already exist, so we only need to set the flag we want (invisib, etc...)</span>
			<span style="color: #a61390;">struct</span> FileInfo <span style="color: #002200;">*</span>finderInfo <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> FileInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>catInfo.finderInfo;
&nbsp;
			<span style="color: #11740a; font-style: italic;">// File type</span>
			finderInfo<span style="color: #002200;">-</span>&gt;fileType <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">'icon'</span>;
			finderInfo<span style="color: #002200;">-</span>&gt;fileCreator <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">'MACS'</span>;
&nbsp;
			<span style="color: #11740a; font-style: italic;">// Icon files should be invisible.</span>
			finderInfo<span style="color: #002200;">-</span>&gt;finderFlags <span style="color: #002200;">=</span> kIsInvisible;
			finderInfo<span style="color: #002200;">-</span>&gt;location.h <span style="color: #002200;">=</span> finderInfo<span style="color: #002200;">-</span>&gt;location.v <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
			<span style="color: #11740a; font-style: italic;">// Standard reserved-field practice.</span>
			finderInfo<span style="color: #002200;">-</span>&gt;reservedField <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
			FSSetCatalogInfo <span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>iconrFSRef, kFSCatInfoFinderInfo, <span style="color: #002200;">&amp;</span>catInfo<span style="color: #002200;">&#41;</span>;
		<span style="color: #002200;">&#125;</span>
	<span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Get the filename, to be applied to the Icon file.</span>
    filename.length <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Icon<span style="color: #2400d9;">\r</span>&quot;</span> length<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Icon<span style="color: #2400d9;">\r</span>&quot;</span> getCharacters<span style="color: #002200;">:</span>filename.unicode<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Make sure the file has a resource fork that we can open.  (Although</span>
    <span style="color: #11740a; font-style: italic;">// this sounds like it would clobber an existing resource fork, the Carbon</span>
    <span style="color: #11740a; font-style: italic;">// Resource Manager docs for this function say that's not the case.)</span>
    FSCreateResFile<span style="color: #002200;">&#40;</span>
                    <span style="color: #002200;">&amp;</span>targetFolderFSRef,
                    filename.length,
                    filename.unicode,
                    kFSCatInfoFinderInfo,
                    <span style="color: #002200;">&amp;</span>catInfo,
                    <span style="color: #002200;">&amp;</span>iconrFSRef,
                    <span style="color: #11740a; font-style: italic;">/*newSpec*/</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    result <span style="color: #002200;">=</span> ResError<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>result <span style="color: #002200;">==</span> noErr || result <span style="color: #002200;">==</span> dupFNErr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Open the file's resource fork.</span>
    file <span style="color: #002200;">=</span> FSOpenResFile<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>iconrFSRef, fsRdWrPerm <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>file <span style="color: #002200;">==</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Make a copy of the icon family data to pass to AddResource().</span>
    <span style="color: #11740a; font-style: italic;">// (AddResource() takes ownership of the handle we pass in; after the</span>
    <span style="color: #11740a; font-style: italic;">// CloseResFile() call its master pointer will be set to 0xffffffff.</span>
    <span style="color: #11740a; font-style: italic;">// We want to keep the icon family data, so we make a copy.)</span>
    <span style="color: #11740a; font-style: italic;">// HandToHand() returns the handle of the copy in hIconFamily.</span>
    hIconFamilyCopy <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span> hIconFamily;
    result <span style="color: #002200;">=</span> HandToHand<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>hIconFamilyCopy <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>result <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        CloseResFile<span style="color: #002200;">&#40;</span> file <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Remove the file's existing kCustomIconResource of type kIconFamilyType</span>
    <span style="color: #11740a; font-style: italic;">// (if any).</span>
    hExistingCustomIcon <span style="color: #002200;">=</span> GetResource<span style="color: #002200;">&#40;</span> kIconFamilyType, kCustomIconResource <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> hExistingCustomIcon <span style="color: #002200;">&#41;</span>
        RemoveResource<span style="color: #002200;">&#40;</span> hExistingCustomIcon <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Now add our icon family as the file's new custom icon.</span>
    AddResource<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hIconFamilyCopy, kIconFamilyType,
                kCustomIconResource, <span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\p</span>&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ResError<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        CloseResFile<span style="color: #002200;">&#40;</span> file <span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Close the file's resource fork, flushing the resource map and new icon</span>
    <span style="color: #11740a; font-style: italic;">// data out to disk.</span>
    CloseResFile<span style="color: #002200;">&#40;</span> file <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>ResError<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    result <span style="color: #002200;">=</span> FSGetCatalogInfo<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>targetFolderFSRef,
                              kFSCatInfoFinderInfo,
                              <span style="color: #002200;">&amp;</span>catInfo,
                              <span style="color: #11740a; font-style: italic;">/*outName*/</span> <span style="color: #a61390;">NULL</span>,
                              <span style="color: #11740a; font-style: italic;">/*fsSpec*/</span> <span style="color: #a61390;">NULL</span>,
                              <span style="color: #11740a; font-style: italic;">/*parentRef*/</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> result <span style="color: #002200;">!=</span> noErr <span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Tell the Finder that the folder now has a custom icon.</span>
    <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> FolderInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>catInfo.finderInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span>&gt;finderFlags <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> FolderInfo <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>catInfo.finderInfo<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span>&gt;finderFlags | kHasCustomIcon <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&amp;</span> ~kHasBeenInited;
&nbsp;
    result <span style="color: #002200;">=</span> FSSetCatalogInfo<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>targetFolderFSRef,
                              kFSCatInfoFinderInfo,
                              <span style="color: #002200;">&amp;</span>catInfo<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> result <span style="color: #002200;">!=</span> noErr <span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Notify the system that the target directory has changed, to give Finder</span>
    <span style="color: #11740a; font-style: italic;">// the chance to find out about its new custom icon.</span>
    result <span style="color: #002200;">=</span> FNNotify<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>targetFolderFSRef, kFNDirectoryModifiedMessage, kNilOptions <span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>result <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Nearly 280 Lines of code later and here we are. I&#8217;m sure there is a group of people out there who don&#8217;t care about the internals of how this works and would like to just use the code. In fact I would wager that that&#8217;s probably the majority. Here&#8217;s all you need if that&#8217;s you. Just drop in the files <em>NSString+CarbonFSRefCreation.m, NSString+CarbonFSRefCreation.h, IconFamily.m</em> and <em>IconFamily.h</em> from the Shiny Frog project into your project and you can then change a folder icon with these few lines of code:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">IconFamily <span style="color: #002200;">*</span>fam <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>IconFamily iconFamilyWithContentsOfFile<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>icnsFilepath stringValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>fam setAsCustomIconForDirectory<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>dirPath stringValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>That&#8217;s a lot easier to read and use obviously. I recommend the object oriented approach as it keeps things much cleaner. And as Shiny Frog has released this code under a standard MIT license which allows you to do pretty much whatever you like as long as you maintain the copyright information, you could take the two classes here and create your own framework that you can then just link in whenever you need it.</p>

<h2>Conclusion</h2>

<p>When I searched for code online to figure out how to achieve setting a custom icon for folders it looked pretty slim. Had I needed to track down all of the steps myself it would have, obviously, taken much longer to figure out, but thanks the Shiny Frog, I was able to find the code to do exactly what I wanted. I&#8217;m hopeful that this blog post will hit the search engines and make it easier for folks to find as this seems like a fairly important thing to know how to do. Until next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/06/16/cocoa-tutorial-custom-folder-icons/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Version Control Makes You A Better Programmer</title>
		<link>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/</link>
		<comments>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 17:47:45 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Development Environment]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=130</guid>
		<description><![CDATA[I&#8217;m a believer. I&#8217;ve used version control before, but Marcus has convinced me that with a little known version control system called Git, written by Linus Torvalds (the creator of Linux), version control is not just about versioning, it&#8217;s about expressing yourself with your code and collaborating with others, seamlessly. As memory serves the only [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a believer. I&#8217;ve used version control before, but Marcus has convinced me that with a little known version control system called <a href="http://www.kernel.org/pub/software/scm/git/docs/tutorial.html">Git</a>, written by <a href="http://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a> (the creator of Linux), version control is not just about versioning, it&#8217;s about expressing yourself with your code and collaborating with others, seamlessly.</p>

<p>As memory serves the only time I&#8217;ve used version control in a meaningful way the system I was using was Visual SourceSafe from Microsoft. I know. Blech! It&#8217;s awful! I&#8217;ve <em>pulled</em> code from many a CVS or Subversion repository, but I&#8217;ve never really used them in the way they are intended to be used. Now, thanks to Marcus, I realize that version control isn&#8217;t just about versioning any more. It&#8217;s a whole methodology/ideology that makes better programmers. Here is what I mean.
<span id="more-130"></span></p>

<h2>Branching Inspires Wild Experimentation</h2>

<p>Have you ever been so far down a path in your code that you just think, though you probably should, there is no way you would take a chance to re-factor due to looming deadlines or even just a simple fear that you might mess up so badly you couldn&#8217;t recover? Well, fear no more! Git provides such a simple way to create a branch of your code in which you can experiment, you won&#8217;t even give it a second thought. I won&#8217;t go into the whole setup and how to get going with Git as this is done very well elsewhere <a href="http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/">including a previous post from Marcus</a>. I just want to point out how easy it is to branch with a single command. In Terminal.app, <em>cd</em> to the directory of a project you have under Git source control and enter the following command.
<pre>
bash$ git branch experimental
</pre>
That&#8217;s all there is to it. You now have a nice shiny clean slate to experiment with abandon. You simply type:
<pre>
bash$ git checkout experimental
</pre>
and you are now working on the <em>experimental</em> branch you just created. Now you can just run amok and have nothing to worry about. Make crazy experimental changes to your heart&#8217;s content and all you need to do to go back to your original code base is type:
<pre>
bash$ git checkout master
</pre>
and you&#8217;re back in business. If you found that your crazy coding excursion was a great success, you can merge your changes in with the following commands.
<pre>
bash$ git checkout master
bash$ git merge experimental
</pre>
The first command switches you back to the <em>master</em> branch, while the second performs the merge of the code from the <em>experimental</em> branch into the <em>master</em> branch. If there are conflicts, you will have to fix them manually, but it seems that the need to do so is pretty rare. Git does a great job at merging changes automatically.</p>

<p>If you found, conversely, that your ideas were purely delusional&#8211;a characteristic of your over-achieving sense of hubris&#8211;you can blow them away by simply typing:
<pre>
bash$ git branch -d experimental
</pre></p>

<p>Now the idea is just a bad memory and not something you ever need worry about (or mention to your programming peers) again. Your code on the master branch is still as it was when you first started the branch. Hallelujah!</p>

<blockquote><strong>Note:</strong> The word &#8216;experimental&#8217; I&#8217;ve used in these command line examples is simply a tag. You can call your branch whatever you like. Call it &#8216;hubris&#8217; if you like. Depending on your personality, this may be more appropriate.</blockquote>

<p>The chance to experiment so easily and without fear will make you a better programmer. You will venture into areas that you would have never tried before and will likely become more bold in what you&#8217;re willing to attempt. This can only be a good thing in the long run.</p>

<h2>Collaboration</h2>

<p>The <a href="http://www.kernel.org/pub/software/scm/git/docs/tutorial.html">Tutorial introduction to git</a> provides a good example of how to collaborate when multiple people are working on the same computer, but where Git&#8217;s real power comes in is in its ability to enable collaboration. If you&#8217;re familiar with extreme programming or pair programming then you are already aware of how collaboration will make you a better programmer. The learning curve for developing applications for the Macintosh for me has been significantly leveled as Marcus has shown me how to do things in the context of real code. You can learn things in many different ways, but sharing code has got to be one of the strongest means of gaining deeper understanding. This can only make you a better programmer.</p>

<p>While not a direct feature of Git itself, you can share your repository over the many file sharing web applications out there. Marcus and I use <a href="http://www.getdropbox.com/">Dropbox</a> for our projects that we collaborate on. Here are the steps you take to collaborate remotely using Git and Dropbox.</p>

<ol>
<li>Sign up and install Dropbox from <a href="http://www.getdropbox.com/">http://www.getdropbox.com</a>.<br />
<br />This will create a folder in your home directory under <em>~/Dropbox</em>.</li>

<li>Have the person you want to collaborate with do the same and then create a shared folder that both of you can access through the Dropbox web interface.<br /><br /></li>

<li>From the project directory of the project you want to share, type:
<pre>
bash$ git clone --bare . ~/Dropbox/Shared/MySharedProject.git
</pre>
<blockquote>
<strong>Note:</strong> Keep in mind that I&#8217;m assuming you already have this project under Git version control. If not you first need to run init like so in the root of your project directory.
<pre>
bash$ git init
</pre>
</blockquote>

The <strong>&#8211;bare</strong> keyword we used in the clone command means that we simply want to create a directory that contains the contents of the .git directory in your project directory and not the actual workspace. The .git directory contains all of your code and changes to everything you need is there&#8211;it&#8217;s just not the actual workspace where xcode works from. 

</li>
<li>Create a remote (alias) for the newly cloned project by typing:
<pre>
bash$ git remote add sharedproject ~/Dropbox/Shared/MySharedProject.git
</pre>
</li><br />
<li>Now you can push any code changes from your working directory to the cloned directory, which, since it is in your <em>Dropbox</em> will automatically be uploaded to the drop box and downloaded by any other computers you have that can access <em>Dropbox</em>. First you need to commit any changes in your working directory with the following command.
<pre>
bash$ git commit -a -m "Commit message"
</pre>
Then you need to push the changes to the remote with the following.
<pre>
bash$ git push sharedproject master
</pre>
This pushes your changes to the cloned repository which is in your </em>Dropbox</em> directory. As soon as you do this, you should see the <em>Dropbox</em> icon in your menu bar change to the &#8216;synchronizing&#8217; icon. If your change is small, it will only change for a split second so you&#8217;ll have to watch it closely to see that happen.
</li>
</ol>

<p>Once your files are committed and have been pushed to your cloned repository, you can now <em>pull</em> the project from another computer. I&#8217;m assuming you have <em>Git</em> and <em>Dropbox</em> set up on the second computer. Here are the steps you take to get the code into Git.</p>

<ol>
<li>In Terminal.app on your other computer, create a new directory where you want your project to be stored with a working directory. Now run the following command.
<pre>
bash$ git clone ~/Dropbox/Shared/MySharedProject.git
</pre>
Notice that we didn&#8217;t use the <strong>&#8211;bare</strong> keyword this time. This is because we want our cloned copy to also setup a working directory since we&#8217;ll be accessing it from xcode on the second computer as well.
</li>
<li>Now create a remote (alias) to reference the project like you did on the other computer using the following.
<pre>
bash$ git remote add sharedproject ~/Dropbox/Shared/MySharedProject.git
</pre>
<blockquote><strong>Note:</strong> This step is optional as your clone will do this automatically. The difference, however, is that the clone will create a remote called &#8216;origin&#8217; by default where you can name it whatever you want (sharedproject in the example) if you do run it.</blockquote>
</li>
<li>Now you can pull the code at any time with the following command.
<pre>
bash$ git pull sharedproject master
</pre>
You won&#8217;t need to do that at this point as your code is fresh from the clone, however, should you make any changes on the originating computer that have been pushed, you could now pull those changes from this secondary computer.
</ul>
</ol>

<p>If you now make changes to the code on the second computer, you can use the exact same command you used on the first computer to push the changes. First commit the changes with:
<pre>
bash$ git commit -a -m "Commit message"
</pre>
Then simply push the changes to the cloned repository with:
<pre>
bash$ git push sharedproject master
</pre></p>

<p>And now you&#8217;re up to date. The changes are ready to be downloaded from the first computer.</p>

<h2>The Urge To Merge</h2>

<p>Nothing like sexual inuendo (urge to merge, hint hint, wink wink) on a site called &#8216;Cocoa is my Girlfriend&#8217; to get a geek going, but that&#8217;s not what I mean. Settle down. Take it easy&#8230;</p>

<p>In the end, Git&#8217;s greatest feature is its ability to merge code changes.</p>

<p>There are times when you have fairly complex code merges that are necessary and systems such as CVS or SVN (Subversion) will simply choke and give up leaving the messy merging process to your weak manual merging skills. This is a shame and not necessary any more as it is rare for Git to be unable to successfully merge code. Again, this probably its biggest strength. When you don&#8217;t have to worry about merging your code, you can do whatever you like in your branch with little fear that merging in your changes are going to conflict with someone else&#8217;s. This merging power comes from Git&#8217;s unique philosophy of source code management which sees changes as individual code additions and deletions rather than complete file changes.</p>

<h2>Conclusion</h2>

<p>There will remain naysayers who have &#8220;always done it this way&#8221; and will remain in the realm of central repositories for version control. However, if you can think outside of tradition and see the power that comes from a good source control system, you will become a better programmer. I will submit that simply starting to use any version control when you haven&#8217;t before will make you a better programmer, however, using Git for your version control system, will make it infinitely easier to become so.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Expanding NSError Usage</title>
		<link>http://www.cimgf.com/2008/05/19/cocoa-tutorial-expanding-nserror-usage/</link>
		<comments>http://www.cimgf.com/2008/05/19/cocoa-tutorial-expanding-nserror-usage/#comments</comments>
		<pubDate>Tue, 20 May 2008 04:11:04 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=128</guid>
		<description><![CDATA[As a follow-up to the previous blog post: Cocoa Tutorial: Using NSError to Great Effect; in this post I am going to demonstrate a few things that can be done with NSError objects that have been received. Specifically, how to add options to an NSError and how to (hopefully) recover from one. The Responder Chain [...]]]></description>
			<content:encoded><![CDATA[<p>As a follow-up to the previous blog post: <a href='http://www.cimgf.com/2008/04/04/cocoa-tutorial-using-nserror-to-great-effect/'>Cocoa Tutorial: Using NSError to Great Effect</a>; in this post I am going to demonstrate a few things that can be done with NSError objects that have been received.  Specifically, how to add options to an NSError and how to (hopefully) recover from one.
<span id="more-128"></span></p>

<h2>The Responder Chain</h2>

<p>The handling of NSError objects follows the responder chain with regard to consuming and manipulating the NSError object.  At any level in the responder chain the error can be displayed and/or handled and thereby consumed.  If the current object in the responder chain does not handle it (which is common), then it is passed up until it finally reaches the NSApplication object.  When it is received by the NSApplication object, that is when the default dialog is presented to the user.</p>

<p>However, that default dialog is not very friendly.  There are no options, very little information, and generally nothing that can be done.  Fortunately, there are ways to customize this presentation and give the user choices.</p>

<h2>Handling an NSError</h2>

<p><img src="http://www.cimgf.com/wp-content/uploads/2008/05/errordialogwithrecovery.png" alt="ErrorDialogWithRecovery.png" border="0" width="50%" align="right" />
To help make this clearer, I am going to demonstrate how to handle an NSError before I demonstrate how to customize the NSError for handling.  To get Cococa to give a user more information and to give the user choices, a few more keys need to be added into the NSError object.  The proper place to add these additional keys is discussed below.</p>

<ul>
<li><strong>NSLocalizedRecoverySuggestionErrorKey</strong>
This key stores a localized string that will be displayed in the &#8220;info&#8221; portion of the alert window/sheet that is displayed to the user.  This string is meant to display suggestive information to the user to make their choice easier.  An example would be &#8220;Do you want to try again?&#8221;</li><br/>

<li><strong>NSRecoveryAttempterErrorKey</strong>
This key points to an object that is to receive the answer to the recovery question.  For example, if you have a dialog that has the options &#8220;Abort&#8221; and &#8220;Try Again&#8221;, this object would receive the answer to that question.  The exact method is discussed below.</li><br/>

<li><strong>NSLocalizedRecoveryOptionsErrorKey</strong>
This key points to an array of strings that are the localized button titles which are displayed to the user.  To follow the examples above, this key would store an array with two strings: &#8220;Try Again&#8221; and &#8220;Abort&#8221;.</li><br/>
</ul>

<p>The recovery attempt object is very similar to a delegate of the NSError responder chain.  When the dialog is presented the recovery attempt object will receive a call once the user makes a choice.  Depending on the type of alert (modal vs. sheet), two different methods can be called:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>attemptRecoveryFromError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error 
                     optionIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>recoveryOptionIndex;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>attemptRecoveryFromError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error 
                     optionIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>recoveryOptionIndex 
                        delegate<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>delegate 
              didRecoverSelector<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>didRecoverSelector 
                     contextInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>contextInfo;</pre></td></tr></table></div>


<p>The first method returns a BOOL to let the caller know whether or not the error was successfully handled.  The second method expects the delegate object to be called.  The delegate method should be similar to:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>didPresentErrorWithRecovery<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>didRecover 
                        contextInfo<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>contextInfo;</pre></td></tr></table></div>


<p>With the BOOL parameter describing whether or not recovery was successful and the contextInfo being the same object passed in.</p>

<h2>Customing the NSError</h2>

<p>When the developer is the one who creates the error message, it is pretty easy to prepare it for handling right at creation.  However, when the creation point of the NSError is either not the appropriate place to set it up for handling or is in someone else&#8217;s code, there are other chances to update the error with handling information.</p>

<p>If you want to capture an NSError and inject the handler information discussed above, then you need to implement a method that will be called as part of the responder chain.  If you want to intercept the error at some point before the NSApplication&#8217;s delegate, then the following method needs to be implemented:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>willPresentError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error;</pre></td></tr></table></div>


<p>However, if you want to manipulate the error at the Application delegate the following method is appropriate:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSApplication</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>app 
       willPresentError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error;</pre></td></tr></table></div>


<p>In this method, you can either return the NSError object that is being passed in, or you can create a new NSError object and return it.  In either case, the error chain will use whatever object is returned from this method.</p>

<h2>Conclusion</h2>

<p>With these methods, it is possible to drastically improve the handling and presentation of errors.  With these methods, errors can be reduced to simple decisions for the user to resolve rather than application crashing events.</p>

<p>I have attached the project from the previous NSError article.  In addition, that project has been updated to utilize the methods described in this entry.</p>

<p><center><a href="http://www.cimgf.com/wp-content/uploads/2008/05/nserrortutorial.zip" title="NSErrorTutorial.zip"><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="128"/><br/>NSError Tutorial</a></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/05/19/cocoa-tutorial-expanding-nserror-usage/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: Get The Most Out of Key Value Coding and Observing</title>
		<link>http://www.cimgf.com/2008/04/15/cocoa-tutorial-get-the-most-out-of-key-value-coding-and-observing/</link>
		<comments>http://www.cimgf.com/2008/04/15/cocoa-tutorial-get-the-most-out-of-key-value-coding-and-observing/#comments</comments>
		<pubDate>Wed, 16 Apr 2008 04:17:56 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[key value coding]]></category>
		<category><![CDATA[key value observing]]></category>
		<category><![CDATA[kvc]]></category>
		<category><![CDATA[kvo]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=96</guid>
		<description><![CDATA[Key Value Observing/Key Value Coding (KVO/KVC) is probably one of the most powerful and most under-utilized features of Objective-C. Here are a couple of examples of how to get the most out of it When a call is made on an object through Key Value Coding such as [self valueForKey:@"someKey"], numerous attempts are made to [...]]]></description>
			<content:encoded><![CDATA[<p>Key Value Observing/Key Value Coding (KVO/KVC) is probably one of the most powerful and most under-utilized features of Objective-C.  Here are a couple of examples of how to get the most out of it</p>

<p>When a call is made on an object through Key Value Coding such as <strong>[self valueForKey:@"someKey"]</strong>, numerous attempts are made to resolve the call.  First, the <em>method</em> someKey is looked for.  If that is not found then the <em>iVar</em> someKey is looked for.  If neither of those are found, then one last attempt is made before presenting an error.  That last attempt is a call to the method <strong>-(id)valueForUndefinedKey:</strong>.  If that method is not implemented then an NSUndefinedKeyException is raised.</p>

<p><strong>valueForUndefinedKey:</strong> is designed so that when you request a value from an object using <strong>-(id)valueForKey:</strong> the object has a last chance to respond to that request before an error occurs. This has many benefits and I have included two examples of those benefits in this post&#8211;<em>Core Data Parameters</em> and <em>Data Formatting</em>.</p>

<p><span id="more-96"></span></p>

<h2>Core Data Parameters</h2>

<p>One of the ways in which I use this method is by making a singleton object that responds to parameter requests. This allows any part of the application to ask the singleton for parameters and get them back in a clean block of code rather than having to build an NSFetchRequest each time a parameter is needed. This allows others parts of the application to make simple calls like:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>companyName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Company shared<span style="color: #002200;">&#93;</span> valueForKey<span style="color: #002200;">:</span>kCompanyName<span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>and avoid messy calls like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>companyName <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
<span style="color: #400080;">NSFetchRequest</span> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFetchRequest</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>request setEntity<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> entityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>request setPredicate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name == %@&quot;</span>, kCompanyName<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
companyName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>managedObjectContext executeFetchRequest<span style="color: #002200;">:</span>request error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span> lastObject<span style="color: #002200;">&#93;</span>;
NSAssert<span style="color: #002200;">&#40;</span>error <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error requesting parameter: %@<span style="color: #2400d9;">\n</span>%@&quot;</span>, kCompanyName, error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>Worse is when I want to set a parameter value:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">id</span> parameter;
&nbsp;
<span style="color: #400080;">NSFetchRequest</span> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFetchRequest</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>request setEntity<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> entityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>request setPredicate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name == %@&quot;</span>, key<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
Â 
parameter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>managedObjectContext executeFetchRequest<span style="color: #002200;">:</span>request error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span> lastObject<span style="color: #002200;">&#93;</span>;
NSAssert<span style="color: #002200;">&#40;</span>error <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error getting parameter %@:%@&quot;</span>, key, error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>parameter<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    parameter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span>key forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>value stringValue<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>value description<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span>value forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>As you can see, after the 5th or 6th time of plugging that block of code in just to get a parameter out of the Core Data store &#8212; it gets old. Therefore, I turned to KVC/KVO.</p>

<blockquote><strong>Not:</strong> These parameters are different from using NSUserDefaults.  NSUserDefaults are great for <i>application</i> level parameters.  However, if you need to store <i>document</i> level parameters then NSUserDefaults is the wrong place.</blockquote>

<p>Instead of writing tons of code to access the Core Data Stack, parameter access can be centralized in a singleton.  That singleton can then be exposed to the entire application and any portion of the application can then request or set parameters.  The parameters are then read and set via the <strong>valueForUndefinedKey:</strong> and <strong>setValue:forUndefinedKey:</strong> methods as shown:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>valueForUndefinedKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>key;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSFetchRequest</span> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFetchRequest</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>request setEntity<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> entityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>request setPredicate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name == %@&quot;</span>, key<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #400080;">NSManagedObject</span> <span style="color: #002200;">*</span>parameter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>managedObjectContext executeFetchRequest<span style="color: #002200;">:</span>request error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span> lastObject<span style="color: #002200;">&#93;</span>;
    NSAssert<span style="color: #002200;">&#40;</span>error <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error requesting parameter: %@<span style="color: #2400d9;">\n</span>%@&quot;</span>, key, error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>parameter valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>value forUndefinedKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>key 
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self willChangeValueForKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSFetchRequest</span> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSFetchRequest</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>request setEntity<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> entityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>request setPredicate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSPredicate</span> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name == %@&quot;</span>, key<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #400080;">NSManagedObject</span> <span style="color: #002200;">*</span>parameter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>managedObjectContext executeFetchRequest<span style="color: #002200;">:</span>request error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span> lastObject<span style="color: #002200;">&#93;</span>;
    NSAssert<span style="color: #002200;">&#40;</span>error <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error getting parameter %@:%@&quot;</span>, key, error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>parameter<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        parameter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSEntityDescription</span> insertNewObjectForEntityForName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parameter&quot;</span> inManagedObjectContext<span style="color: #002200;">:</span>managedObjectContext<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span>key forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>value stringValue<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>value description<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>parameter setValue<span style="color: #002200;">:</span>value forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;value&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#91;</span>self didChangeValueForKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>As you can see this code is pretty much identical to the blocks listed above. However, now it is only in one place in the code and not littered around the entire application. In addition, if I ever decide to move the location where parameters are stored, I only have to alter that code once. By using the <strong>valueForUndefinedKey:</strong> method, I can avoid having to alter the code every time I want to store another parameter. Lastly, since the parameter key is considered a value on the singleton object, I can observe it and receive notifications when it changes. This allows me to hook IB bindings directly to the singleton.</p>

<h2>Date Formatting</h2>

<p>While I do not have an axe to grind against dates in Cocoa, in my opinion the formatters could use some work. Localizing dates directly in Interface Builder (along with currency formatters) is a hit or miss situation. For the display of dates, I simply gave up. I can get the localizers to work just fine in code and I can manually set the formatters for display but there is an easier way to do it.</p>

<p>As part of my modified Core Data Stack, I have a parent class that subclasses NSManagedObject.  All of my objects then extend this subclass.  This (super/sub)class allows me to load in some interesting things such as overriding the <strong>valueForUndefinedKey:</strong> method. In this case, however, I am doing some trickery on the key itself.</p>

<p>As an example, most of my data objects have a value called â€˜createDateâ€™ that is set in the <strong>awakeFromInsert</strong> method. This attribute is stored in Core Data as an NSDate. To get around the issues with the date formatters in InterfaceBuilder, I overrode the <strong>valueForUndefinedKey:</strong> method in the ZDSManagedObject as follows:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> <span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> <span style="color: #a61390;">const</span> kZDSLocalDateStringSuffix <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;LocalString&quot;</span>;
<span style="color: #a61390;">static</span> <span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> <span style="color: #a61390;">const</span> kZDSLocalDateTimeStringSuffix <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;LocalDTString&quot;</span>;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>valueForUndefinedKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>key
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>key hasSuffix<span style="color: #002200;">:</span>kZDSLocalDateStringSuffix<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">id</span> value <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self valueForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>key substringToIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>key rangeOfString<span style="color: #002200;">:</span>kZDSLocalDateStringSuffix<span style="color: #002200;">&#93;</span>.location<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>value<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>super valueForUndefinedKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate shortDateFormatter<span style="color: #002200;">&#93;</span> stringFromDate<span style="color: #002200;">:</span>value<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>super valueForUndefinedKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>key hasSuffix<span style="color: #002200;">:</span>kZDSLocalDateTimeStringSuffix<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">id</span> value <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self valueForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>key substringToIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>key rangeOfString<span style="color: #002200;">:</span>kZDSLocalDateTimeStringSuffix<span style="color: #002200;">&#93;</span>.location<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>value<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>super valueForUndefinedKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>value isKindOfClass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate shortDateTimeFormatter<span style="color: #002200;">&#93;</span> stringFromDate<span style="color: #002200;">:</span>value<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>super valueForUndefinedKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>super valueForUndefinedKey<span style="color: #002200;">:</span>key<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>With this code in place, I can set the createDate binding in Interface Builder to <strong>createDateLocalString</strong> and the field will be populated with the create date formatted properly for the locale. I can also set the binding to <strong>createDateLocalDTString</strong> and receive the date and time formatted properly for the locale.</p>

<h2>Conclusion</h2>

<p>There is a lot more than can be done with Key Value Coding and Observing and the undefinedKey methods.  These two examples are just a start of what can be done to easily and cleanly roll up code that is reused frequently.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/04/15/cocoa-tutorial-get-the-most-out-of-key-value-coding-and-observing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
