<?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>djehuti.com - The Armory &#187; Tips</title>
	<atom:link href="http://www.djehuti.com/category/tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.djehuti.com</link>
	<description>Mac and Music geekery. Not much heraldry talk.</description>
	<lastBuildDate>Wed, 09 Nov 2011 16:51:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Nerdy Mac Tip</title>
		<link>http://www.djehuti.com/2011/09/19/nerdy-mac-uuid-tip/</link>
		<comments>http://www.djehuti.com/2011/09/19/nerdy-mac-uuid-tip/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 16:16:23 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://www.djehuti.com/?p=114</guid>
		<description><![CDATA[Here&#8217;s a nerdy tip for Mac users. Open Automator, and create a new Service workflow. Set it to receive no input, then drag a &#8220;Run Shell Script&#8221; item into the workflow. Replace the default &#8220;cat&#8221; in the text area with this: echo -n `uuidgen &#124; tr A-Z a-z` &#124; pbcopy Save the service as &#8220;Copy [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a nerdy tip for Mac users. Open Automator, and create a new Service workflow. Set it to receive no input, then drag a &#8220;Run Shell Script&#8221; item into the workflow. Replace the default &#8220;cat&#8221; in the text area with this:</p>

<p><code>echo -n `uuidgen | tr A-Z a-z` | pbcopy</code></p>

<p>Save the service as &#8220;Copy New UUID to Pasteboard&#8221;. Now whenever you run the service, it generates a fresh UUID that is on your pasteboard, which you can then copy into whatever context you need it.</p>

<p>If you never need a UUID, then, umm, maybe just don&#8217;t worry about this tip.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.djehuti.com/2011/09/19/nerdy-mac-uuid-tip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designated Initializers in Objective-C</title>
		<link>http://www.djehuti.com/2010/09/21/designated-initializers-in-objective-c/</link>
		<comments>http://www.djehuti.com/2010/09/21/designated-initializers-in-objective-c/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 23:42:24 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.djehuti.com/?p=81</guid>
		<description><![CDATA[So, if you are a Mac/Objective-C developer, you are probably familiar with the Designated Initializer. The Designated Initializer (“DI”) is, in an Objective-C class, the one initializer in a class that is supposed to do the heavy lifting in initializing an object for use. Other initializers of the class should generally invoke the DI. Similarly, [...]]]></description>
			<content:encoded><![CDATA[<p>So, if you are a Mac/Objective-C developer, you are probably familiar with
the <em><a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html%23//apple_ref/doc/uid/TP30001163-CH22-SW8">Designated Initializer</a></em>. The Designated Initializer (“DI”) is, in an Objective-C class, the one initializer in a class that is supposed to do the heavy lifting in initializing an object for use. Other initializers of the class should generally invoke the DI.</p>

<p>Similarly, subclasses of a given class should, in <em>their</em> DI, invoke the superclass DI (and the other initializers of the subclass should invoke the subclass DI).
This way, any way the object gets initialized, the DI of both the superclass and the subclass are sure to be invoked.</p>

<p>The <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html%23//apple_ref/doc/uid/TP30001163-CH22-SW8">documentation</a> does a decent job of explaining this, but I think it&#8217;s easy to miss an important detail, and that is that in a subclass, you must take care not only to <em>invoke</em> the superclass&#8217; DI, but <em>you also have to override it</em>.  (If your DI is different from the superclass&#8217; DI, this is not necessarily obvious.)</p>

<p>For example, take these two classes:</p>

<pre><code>@interface DJMySuperclass : NSObject
{
    DJMyInfo* importantData_;
    BOOL someImportantSwitch_;
}

// The designated initializer for DJMySuperclass:
- (id) initWithImportantData:(DJMyInfo*)importantData;

@end

@interface DJMySubclass : DJMySuperclass
{
    DJMoreInfo* moreImportantData_;
}

// The designated initializer for DJMySubclass:
- (id) initWithImportantData:(DJMyInfo*)importantData
           moreImportantData:(DJMoreInfo*)moreImportantData;

@end
</code></pre>

<p>Fairly straightforward so far, right? Now, take this implementation:</p>

<pre><code>@implementation DJMySuperclass

- (id) init
{
    return [self initWithImportantData:nil];
}

- (id) initWithImportantData:(DJMyInfo*)importantData
{
    if (self = [super init]) {
        if (importantData) {
            importantData_ = [importantData retain];
        } else {
            importantData_ = [[DJMyImportantData alloc] init];
        }
        someImportantSwitch_ = YES;
    }
    return self;
}

- (void) dealloc
{
    [importantData_ release];
    [super dealloc];
}

@end
</code></pre>

<p>So far so good; completely obvious. Now let&#8217;s take this subclass implementation:</p>

<pre><code>@implementation DJMySubclass

- (id) init
{
    return [self initWithImportantData:nil moreImportantData:nil];
}

- (id) initWithImportantData:(DJMyInfo*)importantData
           moreImportantData:(DJMoreInfo*)moreImportantData
{
    if (self = [super initWithImportantData:importantData]) {
        someImportantSwitch_ = NO;
        if (moreImportantData) {
            moreImportantData_ = [moreImportantData retain];
        } else {
            moreImportantData_ = [[DJMoreInfo alloc] init];
        }
    }
    return self;
}

- (void) dealloc
{
    [moreImportantData_ release];
    [super dealloc];
}

@end
</code></pre>

<p>Again, totally straightforward, right? So where is the bug?</p>

<p>Imagine this extension (or, maybe instead of a category extension, imagine a similar future addition to the superclass and subclass, a year down the road and done by a different developer).</p>

<pre><code>@interface DJMySuperclass(JBJoeBlowsAdditions)

- (id) JB_returnsACopy;

@end

@implementation DJMySuperclass(JBJoeBlowAdditions)

- (id) JB_returnsACopy
{
    return [[[[self class] alloc] initWithImportantData:importantData_] autorelease];
}

@end

@implementation DJMySubclass(JBJoeBlowAdditions)

- (id) JB_returnsACopy
{
    DJMySubclass* other = [super JB_returnsACopy];
    [other-&gt;moreImportantData_ release];
    other-&gt;moreImportantData_ = [moreImportantData_ retain];
    return other;
}

@end
</code></pre>

<p>Where&#8217;s the bug?</p>

<p>The bug is that if you have a <code>DJMySubclass</code> object called <code>foo</code>, and you
call <code>DJMySubclass* bar = [foo JB_returnsACopy];</code>, you&#8217;ll discover that
<code>bar-&gt;someImportantSwitch_</code> contains <code>YES</code>, when you thought you had a class invariant for <code>DJMySubclass</code> where <code>someImportantSwitch_</code> was always forced to <code>NO</code>.</p>

<p>Why?</p>

<p>Because <code>JB_returnsACopy</code> in the superclass uses the <code>initWithImportantData:</code> initializer, and you didn&#8217;t cover it in <code>DJMySubclass</code>, so <em>your designated initializer in the subclass never got invoked</em>.</p>

<p>The fix is simple: cover the superclass&#8217; DI in your subclass, and invoke your DI.</p>

<pre><code>@implementation DJMySubclass

- (id) initWithImportantData:(DJMyInfo*)importantData
{
    return [self initWithImportantData:importantData
                     moreImportantData:nil];
}

@end
</code></pre>

<p>The <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html%23//apple_ref/doc/uid/TP30001163-CH22-SW8">documentation</a> for Designated Initializers says:</p>

<blockquote>
  <p>It’s important to know the designated initializer when defining a subclass.
  For example, suppose we define class C, a subclass of B, and implement an
  <code>initWithName:fromFile:</code> method. In addition to this method, we have to make
  sure that the inherited <code>init</code> and <code>initWithName:</code> methods also work for
  instances of C. This can be done just by covering B’s <code>initWithName:</code>
  with a version that invokes <code>initWithName:fromFile:</code>.</p>
  
  <p>&#8230;</p>
  
  <p><strong>General Principle</strong>: The designated initializer in a class must, through a
  message to <code>super</code>, invoke the designated initializer in a superclass.</p>
</blockquote>

<p>This general principle, while true, is not sufficient. You really need to
make sure to <em>cover</em> the superclass&#8217; DI in your subclass, as described in that
first paragraph, and shown in the accompanying diagram 3-3.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.djehuti.com/2010/09/21/designated-initializers-in-objective-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comprehensive Flowchart</title>
		<link>http://www.djehuti.com/2009/06/22/comprehensive-flowchart/</link>
		<comments>http://www.djehuti.com/2009/06/22/comprehensive-flowchart/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 19:34:22 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[kids]]></category>

		<guid isPermaLink="false">http://www.djehuti.com/?p=38</guid>
		<description><![CDATA[I&#8217;ve come up with a comprehensive flowchart for children to follow, outlining proper behavior in all cases. It can be used in all situations and I&#8217;ve think I&#8217;ve covered all the bases, enough to handle any scenario that they should be expected to encounter. Unfortunately I think it may be too complex for most children [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve come up with a comprehensive flowchart for children to follow, outlining proper behavior in all cases. It can be used in all situations and I&#8217;ve think I&#8217;ve covered all the bases, enough to handle any scenario that they should be expected to encounter. Unfortunately I think it may be too complex for most children under the age of 8 to navigate successfully. See what you think. I&#8217;ve shown it below.</p>

<p><img src="/images/flowchart.png" alt="Flowchart" /></p>

<p>(Reposted from my internal blog at work.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.djehuti.com/2009/06/22/comprehensive-flowchart/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

