<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Corporation Unknown]]></title>
  <link href="http://corporationunknown.com/atom.xml" rel="self"/>
  <link href="http://corporationunknown.com/"/>
  <updated>2017-04-27T11:35:33-07:00</updated>
  <id>http://corporationunknown.com/</id>
  <author>
    <name><![CDATA[Paul Goracke]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[My E-Reading Quirks]]></title>
    <link href="http://corporationunknown.com/blog/2015/01/04/my-e-reading-quirks/"/>
    <updated>2015-01-04T19:17:22-08:00</updated>
    <id>http://corporationunknown.com/blog/2015/01/04/my-e-reading-quirks</id>
    <content type="html"><![CDATA[<p>I love paper books, but I&rsquo;m not a fetishist. I&rsquo;ve gone almost entirely digital for my technical books since they tend to be relatively massive and become outdated quickly.</p>

<p>E-Readers are such different experiences from paper books, but we seem to have already settled on interface paradigms that carry over so much paper baggage. For a while now I&rsquo;ve noticed that I have adopted a few counter-intuitive e-reading practices that others haven&rsquo;t.</p>

<!-- more -->


<h2>&ldquo;Both Margins Advance&rdquo;</h2>

<p>The typical e-reader paradigm is to swipe right-to-left or left-to-right to turn the page forward or back, respectively, and to tap the right or left margins to advance or page back. &ldquo;Duh, obvious,&rdquo; right? But is this really needed?</p>

<p>By my (highly scientific, trust me!) estimate, more than 95% of reading is moving forward&mdash;why should half of the interface be devoted to moving back? If you are right-handed, have you <em>tried</em> holding the iPad in your left hand and advancing pages while enjoying a fresh cup of coffee? Swiping is possible, but it&rsquo;s awkward.</p>

<p>iBooks has a &ldquo;Both Margins Advance&rdquo; option in its Settings.app bundle. I don&rsquo;t know if this was a sop to lefties, but for me it has become a defining feature for any good e-reader. By enabling this option, tapping either the left <em>or</em> right margin advances the page. You still have left-to-right swipe capability for the exceptional instances when you need to go back. Tapping either margin allows for comfortable ambidextrous one-hand reading while enjoying a tasty beverage or (as in my original use case when I discovered this) holding a sleeping infant.</p>

<h2>On the iPhone, Read <em>Less</em> Not More</h2>

<p>If you read on your iPhone but it&rsquo;s not your primary reading device, go make your e-reader font bigger. No, bigger than that.</p>

<p>No&hellip;still bigger. Really.</p>

<p>On my iPhone 5, my font is set so I typically only see 13 lines of body text per screen. That&rsquo;s not much; you&rsquo;ve probably actively been going the other direction trying to squeeze in a &ldquo;page&rdquo; per screen. While I initially made this adjustment due to getting older and denying that I needed reading glasses, it&rsquo;s turned out to be more generally useful.</p>

<p>When I&rsquo;m comfortably settled in for reading, I use my iPad. I really only read on my iPhone when I&rsquo;m on the go, which turns out to be highly interruptible: I&rsquo;m frequently glancing up to see if the bus is coming, or if it&rsquo;s my turn to speak to a clerk. Larger fonts don&rsquo;t necessarily help so much with the <em>reading</em> of text on iPhone as much as they help you <em>return to reading</em> after an interruption. You have much less positioning on screen to remember and can return to where you were much quicker. If this describes your reading conditions, give this tip a try&mdash;trust me, you&rsquo;ll quickly get used to the more frequent paging required.</p>

<h2>Wish List Items</h2>

<p>I wish iBooks gave me better control of styles. Most notably, I&rsquo;d like to be able to reduce the size of chapter and section headings so they don&rsquo;t overwhelm the iPhone screen at my larger font size.</p>

<p>I&rsquo;d like the ability for the screen to be <em>less</em> reactive while I&rsquo;m reading. I&rsquo;ve only dabbled in speed reading practices, but one of the first techniques they all promote is to guide your eye along the text with your finger. This is pretty impractical when it can so easily be recognized as a page-turning swipe. I&rsquo;m not really interested in getting into a pros and cons of speed reading discussion, but it is an example case where one would want to be more hands-on with the text than most e-readers allow.</p>

<p>I&rsquo;m really glad e-reading has advanced from when I first started reading on a tiny Handspring Visor. I admire those experimenting with exploring it as its own expressive medium, but I also want developers to continue to question and improve <em>how</em> we read standard texts.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Preloading Development Data Into Your iOS App]]></title>
    <link href="http://corporationunknown.com/blog/2014/07/10/preloading-development-data-into-your-ios-app/"/>
    <updated>2014-07-10T16:36:40-07:00</updated>
    <id>http://corporationunknown.com/blog/2014/07/10/preloading-development-data-into-your-ios-app</id>
    <content type="html"><![CDATA[<p>When it comes to Core Data, many application developers don&rsquo;t even think about migration between versions. Even for those who do consider it, most testing usually ends up limited to a few simplistic scenarios: It&rsquo;s tedious to repeatedly set up a single known state for a data store, and working against a full matrix of viable scenarios is just onerous.</p>

<p>Fortunately, there is functionality within Xcode to make it easier to manage and maintain a number of scenarios and restore them readily. This functionality will allow you to test your migration code from any past data model version to the current version, debug custom migrations, even profile migrations in Instruments.</p>

<p>Unfortunately, it&rsquo;s not very well documented and, while you can preload to a device or simulator, the data package must first be created on a device.</p>

<blockquote><p><em>Update 2015-04-20:</em> This worked great in Xcode 5. Unfortunately Xcode 6 (through 6.3 as of this writing) does not behave as described for the Simulator (it does load a device just fine). Versions &lt;6.3 will tell you &ldquo;The application data package will be installed the next time you run your app in the Simulator&rdquo;&mdash;every time. Version 6.3 will just silently fail to load the package. I have reported this as <a href="rdar://20622011">rdar://20622011</a> / <a href="http://www.openradar.me/radar?id=4545448916287488">Open Radar</a></p></blockquote>

<!-- more -->


<h2>Your Friend the .xcappdata Package</h2>

<p>You&rsquo;ve probably encountered an <code>.xcappdata</code> package before, although you most likely think of it as a one-way data extraction method. Let&rsquo;s walk through this with as simple a demo application as possible:</p>

<ol>
<li>Create a new project. As much as I despise Apple&rsquo;s template Core Data stack, it will suffice for this example, so create a new &ldquo;Master-Detail Application&rdquo; that uses Core Data.</li>
<li>Run the application on a device.</li>
<li><p>Add 5 items.</p>

<p> <img src="http://corporationunknown.com/blog/images/2014/screenshot.png" alt="App Screenshot" /></p></li>
<li>You may stop running the application on your device&mdash;the following steps aren&rsquo;t affected by it running or not.</li>
<li><p>Open the Xcode Organizer, select the &ldquo;Applications&rdquo; section of your device under the Devices tab.</p>

<p> <img src="http://corporationunknown.com/blog/images/2014/organizer.png" alt="Xcode Organizer" /></p></li>
<li>Select your test application. You should see a bunch of folders and files populate the &ldquo;Data files in Sandbox&rdquo;. (This may not populate right away, so be patient.)</li>
<li>Click the &ldquo;Download&rdquo; button at the bottom and save the xcappdata package to your Desktop, giving it a descriptive name like <code>v0 - 5 items.xcappdata</code>.</li>
<li>Click &ldquo;Delete&rdquo; to remove the application from the device&mdash;we will try to start with a clean install for the next steps.</li>
</ol>


<p>Here comes the magic:</p>

<ol>
<li>Create a new Group in your project. I name mine &ldquo;Test Data&rdquo;.</li>
<li>Add <code>v0 - 5 items.xcappdata</code> to the group.

<ol>
<li>Select &ldquo;Copy items into group folder&rdquo;.</li>
<li>Do <em>not</em> add it to any targets.</li>
</ol>


<p> <img src="http://corporationunknown.com/blog/images/2014/project.png" alt="Project Layout" /></p></li>
<li><p>Launch the app while holding the Option key&mdash;either Option-clicking the Run button, or Option-Command-R. A scheme configuration sheet will appear.</p>

<p> <img src="http://corporationunknown.com/blog/images/2014/app_data.png" alt="Choosing Launch Options" /></p></li>
<li>In the Options tab, select <code>v0 - 5 items.xcappdata</code> from the Application Data menu and click &ldquo;Run&rdquo;.</li>
</ol>


<p>Voilá, your app has launched a clean install, but with five items in the database&mdash;Xcode has pre-configured your application with the data files from your xcappdata package.</p>

<h2>Exploring the .xcappdata Package</h2>

<p>In the Finder, Control-click the <code>.xcappdata</code> package and select &ldquo;Show Package Contents&rdquo; from the contextual menu. Inside you will find an <code>AppDataInfo.plist</code> file and an <code>AppData</code> folder. Inside the <code>AppData</code> folder are the <code>Documents</code>, <code>Library</code>, and <code>tmp</code> folders that were downloaded from the device.</p>

<p><img src="http://corporationunknown.com/blog/images/2014/package.png" alt="Package Contents" /></p>

<p>Any changes you make to these folders will be reflected the next time you launch the app with this scheme loading the application data. Let&rsquo;s make a &ldquo;clean launch&rdquo; data set:</p>

<ol>
<li><p>Duplicate <code>v0 - 5 items.xcappdata</code> in the Finder and rename it to <code>Clean Launch.xcappdata</code>.</p>

<p> <img src="http://corporationunknown.com/blog/images/2014/copy_rename.png" alt="Renaming Package" /></p></li>
<li>Open Terminal and Command-drag your <code>Clean Launch.xcappdata</code> onto it to make the package&rsquo;s path your current directory.</li>
<li>Execute <code>rm AppData/Documents/*sqlite*</code> to remove the Core Data store and supporting files.</li>
<li>Execute <code>rm -rf AppData/Library/Caches/*/.CoreDataCaches</code>. This clears out the invisible directory containing all your <code>NSFetchedResultsController</code> caches. If these are out of sync with the data store, you will encounter crashes and other frustrating behavior.</li>
<li>Add <code>Clean Launch.xcappdata</code> to your project, again remembering not to add it to any targets.</li>
</ol>


<p>Now you have a way to start from scratch whenever you want without having to delete the app first.</p>

<h2>Testing Implications</h2>

<p>Every public release version of your app should be the time to freeze the version of your Core Data model. When you release the next version of your app, you will need to account for migrating the data your users currently have to the new version&rsquo;s data model. (There may not actually be any version-to-version changes, but you should assume there will be.)</p>

<p>So as part of every release you should take a few xcappdata snapshots:</p>

<ul>
<li>Empty database. This is <em>not</em> the Clean Launch, this is the default database Core Data would generate, including anything your app automatically constructs. This is the state your app would be in if a user launched it once, didn&rsquo;t do anything, and (horrors!) forgot about your app until launching an updated version.</li>
<li>&ldquo;Typical&rdquo; user database. Run the app for a while as a typical usage scenario, then download the data package. You may have multiple &ldquo;typical&rdquo; users&mdash;make snapshots for all you can define.</li>
<li>&ldquo;Extreme&rdquo; user database. This is your chance to stress test; this is your chance to ensure that your migrations can satisfy even the most outrageous user of your application. If you need to, create a command-line tool to create a large data store using the model then copy that into the package.</li>
</ul>


<p>Add these to your project so they&rsquo;re available to use. Give them descriptive names that include at least the revision (&ldquo;v1&rdquo;, &ldquo;v2&rdquo;) and scenario (&ldquo;base&rdquo;, &ldquo;userA&rdquo;, &ldquo;extreme&rdquo;). Adding them to project groups will help organization, but the scheme menu only lists the package name so make it identifiable.</p>

<p>At some point during the development of your next release, any model updates will have settled down. Use these data sets to verify that:</p>

<ul>
<li>Migration of old versions happens</li>
<li>Migration happens correctly</li>
<li>Migration happens quickly</li>
</ul>


<p>The first two points can be tested in the simulator. If you need to write custom migration code, you will automatically start from the same point every time you launch the app after making code changes.</p>

<p>The last point of verification, though, needs to be run on real devices so you know that users will successfully migrate without having the launch watchdog kill the app launch and launch again.</p>

<p>Keep in mind that successfully migrating in the allotted launch time isn&rsquo;t enough. If the app is to all intents and purposes locked during that time, the user may choose to be the Final Watchdog and terminate your app with extreme prejudice. This is your chance to ensure a positive user experience.</p>

<h2>Manually Updating the Package</h2>

<p>You can manually update the files in an xcappdata package to create a new snapshot, but beware of a few things:</p>

<ul>
<li>&ldquo;Modern&rdquo; SQLite adds <code>.sqlite-shm</code> and <code>.sqlite-wal</code> files next to the <code>.sqlite</code> file for write-ahead logging. Be sure to keep all these files in sync with a changed <code>.sqlite</code> file by using an editor that understands these files (I recommend <a href="http://menial.co.uk/base/">Base</a>, I&rsquo;m sure there are others), or copying/replacing these auxilliary files if you replace one <code>.sqlite</code> file with another.</li>
<li><code>NSFetchedResultsController</code> caches need to stay in sync with data store changes, too. Delete the <code>.CoreDataCaches</code> directory from the package, run this package on a device long enough to exercise all the <code>NSFetchedResultsControllers</code>, then download that package as the one to keep.</li>
<li>Your app is probably more complex than the example shown. Ensure that documents stored external to the SQLite files are where they are expected, and in sync with any other changes.</li>
<li>If you can get a data file from a user or tester who is experiencing problems, that is golden. Migrate that data file into its own package and name it something like <code>v3-bug16002</code> to enshrine it in your migration testing history. Not only will this help you debug it, you will have it available going forward to avoid regressions.</li>
</ul>


<h2>Notes and Tips</h2>

<ul>
<li>The demo app saves the context every time an item is added. If your real code does not do that, be sure <code>-save:</code> is invoked at some point before you try downloading the xcappdata or you will not have the data you thought you had.</li>
<li>Application Data settings persist with the scheme. I find it useful to create a new scheme named &ldquo;Migration Testing&rdquo; and only test migrations with that scheme. This isn&rsquo;t necessary, but it&rsquo;s good to know that when you&rsquo;re using the app&rsquo;s self-titled scheme, you aren&rsquo;t accidentally resetting the data every launch.</li>
<li>Git for one doesn&rsquo;t track empty directories. In my experience it isn&rsquo;t worth worrying about because the app&rsquo;s sandbox gets laid out correctly even without directories like <code>/tmp</code> in the xcappdata package.</li>
<li>Be sure you don&rsquo;t add the packages to the app targets. This just copies them into the app bundle as resources and bloats the app.</li>
</ul>


<h2>Radars</h2>

<ul>
<li>rdar://17495757 &ndash; <a href="http://openradar.appspot.com/radar?id=5876854351200256">iOS NSFetchedResultsController: Stop hiding caches directory</a></li>
<li>rdar://17539241 &ndash; <a href="http://openradar.appspot.com/radar?id=5792266580918272">Xcode: Allow creation of .xcappdata packages from Simulator</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[To NSStringFromSelector or Not]]></title>
    <link href="http://corporationunknown.com/blog/2014/03/24/to-nsstringfromselector-or-not/"/>
    <updated>2014-03-24T00:19:17-07:00</updated>
    <id>http://corporationunknown.com/blog/2014/03/24/to-nsstringfromselector-or-not</id>
    <content type="html"><![CDATA[<p>In my <a href="http://corporationunknown.com/blog/2014/02/16/core-data-potpourri/">&ldquo;Core Data Potpourri&rdquo; talk</a>, I recommend declaring constant NSStrings of NSManagedObject attributes (that&rsquo;s the correct Core Data term, but I&rsquo;m just going to call them &ldquo;properties&rdquo; from here on out) for use in NSPredicates and KVC. Via Twitter, Riley Testut suggested an alternative:</p>

<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/pgor">@pgor</a> have you considered using NSStringFromSelector(<a href="https://twitter.com/Selector">@selector</a>(property)) when having to hardcode a property string? Seems cleanest to me</p>&mdash; Riley Testut (@rileytestut) <a href="https://twitter.com/rileytestut/statuses/447251332399771649">March 22, 2014</a></blockquote>


<script async src="http://corporationunknown.com//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>This <em>does</em> look like it would be cleaner. There&rsquo;s not a &ldquo;magic string&rdquo; involved, and with the &ldquo;Undeclared Selector&rdquo; warning (GCC_WARN_UNDECLARED_SELECTOR) you would be warned if a property changed and your @selector wasn&rsquo;t updated. Upon closer examination, though, there are a few problems.</p>

<!-- more -->


<h1>Problem the First: Declaration</h1>

<p>The proposed construct is not a compile-time constant, so I can&rsquo;t just change my</p>

<div>
  <pre><code class='objective-c'>NSString* const EventKeyTimeStamp = @&quot;timeStamp&quot;;</code></pre>
</div>


<p>line to</p>

<div>
  <pre><code class='objective-c'>NSString* const EventKeyTimeStamp = NSStringFromSelector(@selector(timeStamp));</code></pre>
</div>


<p>There might be a way to pull out some compiler attribute-fu to initialize this properly, but I doubt it would be able to keep the <code>const</code> qualifier that makes me feel safe.</p>

<p>The next step would be to eschew the constant variable declaration and just use a <code>#define</code> in the header:</p>

<div>
  <pre><code class='objective-c'>#define EventKeyTimeStamp NSStringFromSelector(@selector(timeStamp))</code></pre>
</div>


<p>I&rsquo;m not a fan of having actual <em>code</em> in #defines. They always seem to end up causing more trouble and obfuscation than they&rsquo;re worth, particularly when <em>I</em> write them. I&rsquo;d much rather just write a boring function or method that I can breakpoint and walk through as a normal part of my applicaton.</p>

<p>But what the heck, let&rsquo;s go with the precompiler for this one. It works. It substitutes the proper string for KVC and predicates. If you rename the <code>timeStamp</code> property to <code>timestamp</code> it will complain if you don&rsquo;t change the @selector. All looks well.</p>

<h1>Problem the Second: Indiscriminate Selectors</h1>

<p>The confidence we gain from this method is based on the undefined selector warning firing if we change the target property name. Simple testing bears that out but unfortunately that&rsquo;s not the case.</p>

<p>The undefined selector warning will be satisfied if it sees a matching selector anywhere in the current compilation unit. You may think that because our #define is in the NSManagedObject&rsquo;s header, that compilation unit is just the MO and the (hopefully limited) #imports from that header. Unfortunately, #defines are first substituted into the code in-place <em>then</em> evaluated. So when evaluated, its compilation unit includes every header the client code has imported&mdash;if any object in that unit has a matching selector, the warning will be satisfied.</p>

<p>If we rename -timeStamp to -timestamp and <em>any</em> object in the current compilation unit has a -timeStamp method, we will not be warned that we did not update this constant and it will fail in KVC and predicates at runtime.</p>

<p><em>Any</em> object.</p>

<p>If you can <em>guarantee</em> that you can create some code in your project that will never experience that kind of cross-contamination, it can be the alert system for validating your property constants. If not, the confidence using NSStringFromSelector in this case is sadly most likely false confidence.</p>

<p>At this point, I see no benefit to NSStringFromSelector in this manner. Admittedly, my constant string mechanism is no more reliable in alerting me of these problems, but my aversion to code in #define statements will keep me using constant strings.</p>

<h1>Unit Tests!</h1>

<p>If you really want safety for this (and you should), I still believe that unit tests are the most reliable way to do it.</p>

<div>
  <pre><code class='objective-c'>- (void) setUp
{
  [super setUp];
  self.managedObjectContext = [MyTestContext createInMemory];
}

- (void) testAttributes
{
  Event* event = [Event insertNewObjectInManagedObjectContext:self.managedObjectContext];
  
  NSDate* testDate = [NSDate date];
  event.timeStamp = testDate;
  XCTAssertEqualObjects(event.timeStamp, testDate, @&quot;timeStamp property failed to store properly&quot;);
  XCTAssertNoThrow([event valueForKey:EventKeyTimeStamp], @&quot;KVO property '%@' doesn't exist&quot;, EventKeyTimeStamp);
  XCTAssertEqualObjects([event valueForKey:EventKeyTimeStamp], event.timeStamp, @&quot;KVO value differs from property&quot;);
}</code></pre>
</div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[For the Record]]></title>
    <link href="http://corporationunknown.com/blog/2014/02/28/for-the-record/"/>
    <updated>2014-02-28T11:54:04-08:00</updated>
    <id>http://corporationunknown.com/blog/2014/02/28/for-the-record</id>
    <content type="html"><![CDATA[<p>I am honored to be on the latest installment of &ldquo;<a href="http://therecord.co/2014/02/28/paul_goracke">The Record</a>&rdquo; podcast with Brent Simmons and Chris Parrish. Since they interviewed me last summer, I&rsquo;ve been eagerly waiting to hear what they talked about with <em>other</em> interviewees. The first four episodes with Luke Adamson, John Nack, Greg Robbins, and Gus Mueller have been great. It&rsquo;s rather intimidating to think that I might be counted among them.</p>

<p>I don&rsquo;t remember most of what we discussed; I didn&rsquo;t even remember much of it immediately afterward, it flowed so smoothly. One thing I <em>do</em> remember is that I said Metrowerks was integral to the Intel transition&mdash;instead, they were part of the earlier PowerPC transition. I&rsquo;m not a historian of any kind and I don&rsquo;t pretend to be. I misspoke and know it, so I don&rsquo;t need to be set straight. Thanks.</p>

<p>Now I guess I should listen to the episode to be reminded of what I said, even if it involves the agony of listening to my own recorded voice.</p>

<p><em>Update:</em> Huh, I <em>did</em> correctly say &ldquo;PowerPC&rdquo;. See, I&rsquo;m not even a good historian of things that happened less than a year ago.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Core Data Potpourri]]></title>
    <link href="http://corporationunknown.com/blog/2014/02/16/core-data-potpourri/"/>
    <updated>2014-02-16T14:55:51-08:00</updated>
    <id>http://corporationunknown.com/blog/2014/02/16/core-data-potpourri</id>
    <content type="html"><![CDATA[<p>Last Thursday (Feb 13, 2014) I presented a talk to <a href="http://seattlexcoders.org">Seattle Xcoders</a> entitled &ldquo;Core Data Potpourri&rdquo;. On Friday I posted a <a href="http://corporationunknown.com/presentations/Core%20Data%20Potpourri.pdf">PDF version of the slides</a>, primarily so those in attendance would have them. These slides aren&rsquo;t really intended to stand alone&mdash;hell, I wrote them up the day of the presentation&mdash;so I didn&rsquo;t intend to announce them outside Xcoders until the <a href="http://vimeo.com/seattlexcoders">video was posted</a>. (I&rsquo;m not in charge of the encoding, so I don&rsquo;t know yet when it will be posted.)</p>

<p><em>Update:</em> <a href="https://vimeo.com/89370886">Video is now live</a>. <em>-18mar14</em></p>

<p>Then <a href="http://inessential.com/2014/02/14/pauls_talk_on_core_data">Brent Simmons linked to them</a> and I feel like I&rsquo;ve been fielding questions, comments, and a pleasant number of kudos ever since. I feel like I should post some clarifications here now.</p>

<p>This talk was pretty much a <em>complete last minute change</em> from what I&rsquo;d prepared and presented internally to <a href="http://blackpixel.com/">Black Pixel</a> coworkers two days earlier because I wasn&rsquo;t happy with the boring textbook feel of that talk. If you don&rsquo;t feel it was a polished set of slides, you&rsquo;re absolutely correct.</p>

<h1>Multithreading</h1>

<p>Please keep in mind the last few slides on Core Data multithreading are woefully inadequate. I&rsquo;d intended to cover it more thoroughly as part of the &ldquo;potpourri&rdquo; concept but the list of &ldquo;best practices&rdquo; grew to pretty much be a list of many things I&rsquo;ve been ranting about to others for the last year or so, and that I&rsquo;d been sprinkling throughout client projects. I was tempted to ignore it (like I did the empty slides on performance optimization and multiple persistent stores) but felt I should reward people for sticking it out through the talk.</p>

<p>I warned the audience before discussing it that there would be a lot of handwaving and no code examples were ready&mdash;but that surely doesn&rsquo;t come across in static slides.</p>

<h1>Mogenerator</h1>

<p>The &ldquo;Why Not mogenerator&rdquo; slide has been the lightning rod, as I&rsquo;d feared&mdash;I&rsquo;ve learned you can expect that whenever you call something out in <em>any</em> negative light. Hopefully when you see the actual talk, it will come across as I intended: A response for when someone asks me why I do this &ldquo;by hand&rdquo;, not a screed trying to wipe mogenerator from the face of the Earth.</p>

<p>By the way, there&rsquo;s one response to &ldquo;how do you handle when you have to regenerate classes&rdquo; that I didn&rsquo;t even manage to get out during the presentation: Git diff. Honestly.</p>

<h1>Parent-Child Contexts</h1>

<p>This is multifold. First, I consider my &ldquo;enlightenment&rdquo; regarding multithreaded Core Data to have come during a project targeting iOS 5.1. The new contexts weren&rsquo;t an option on the project, and seeing coworkers fight the nightmares of that initial release of contexts convinced me to not bother looking into it for a while. Since then, I&rsquo;ve become comfortable enough in the &ldquo;one reader context, multiple serial writer contexts&rdquo; mechanism that I haven&rsquo;t found many compelling reasons to make parent-child my default.</p>

<p>Second, I strongly believe that <em>understanding</em> the implications and combinations of the rules &ldquo;each MO belongs to only one MOC&rdquo;, &ldquo;MOCs are not threadsafe&rdquo;, and&mdash;perhaps most importantly&mdash;&ldquo;loaded MOs need to refresh somehow&rdquo; are key to writing successful multithreaded code. After that, parent-child contexts can make great tools but too many developers treat them as the cure-all that will let them just ignore these aspects. Parent-child and thread containment can work together, it doesn&rsquo;t have to be either-or.</p>

<h1>Miscellaneous</h1>

<p>It was pointed out after the talk that my &ldquo;+newInstance&hellip;&rdquo; method for managed objects returns an autoreleased object and will break MRC conventions. Totally correct. This is mostly due to me having tried to clear out MRC space in my brain for new knowledge, but also because I threw together the talk with code examples from numerous different projects, and my naming conventions have tended to change over time. I&rsquo;m sure there are other such problems in the slides&mdash;you&rsquo;re free to &ldquo;Be Better Than Sample Code&rdquo;. :)</p>

<p>&ldquo;NSManagedObject Is the Real Top of the Stack&rdquo; might imply that you don&rsquo;t have to worry about keeping a strong reference to that parent MOC. Don&rsquo;t forget that -managedObjectContext is a weak reference and if a MOC is deallocated, any of its MOs are now invalid. In practice, I rarely have an issue with this since I&rsquo;m keeping one readonly MOC around for all my UI needs, but this is definitely something to be aware of. I still feel it&rsquo;s not worth the confusion of passing/configuring them separately.</p>

<p>I hope this clarifies some issues people have had. I hope you watch the video when it&rsquo;s released but be warned that it will probably run about 100 minutes with talk and Q&amp;A. (I&rsquo;m told Q&amp;A was actually truncated due to SD card storage limits.)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[UITableViewCell Is Not a Controller, But…]]></title>
    <link href="http://corporationunknown.com/blog/2013/01/01/uitableviewcell-is-not-a-controller-but/"/>
    <updated>2013-01-01T19:53:42-08:00</updated>
    <id>http://corporationunknown.com/blog/2013/01/01/uitableviewcell-is-not-a-controller-but</id>
    <content type="html"><![CDATA[<p>Brent Simmons wrote a <a href="http://inessential.com/2012/12/31/uitableviewcell_is_not_a_controller">great defense of his proposed &ldquo;Cocoa Sin&rdquo; of &ldquo;Passing model objects to a UITableViewCell subclass&rdquo;</a>, expanding on the one apparently contentious item in his <a href="http://inessential.com/2012/12/31/coders_in_the_hands_of_an_angry_god">great list of 20 sins</a>. Go read both posts, he&rsquo;s so completely right.</p>

<p>Except I disagree.<!-- more --> I&rsquo;ve been down a number of <code>UITableViewCell</code> paths that bit me in the end, many of which Brent seems to have experienced as well, but I have ended up settling on creating <code>UITableViewCell</code> subclasses which take the model object they&rsquo;re intended to display and break out the properties to the individual subviews so the controller doesn&rsquo;t have to.</p>

<p>At its core, I&rsquo;m taking code Brent would write like this:</p>

<div>
  <pre><code class='objective-c'>- (void) updateCell:(MyTableViewCell*)cell 
     forModelObject:(Model*)object 
{
   cell.nameLabel.text = object.name;
   cell.valueLabel.text = object.value;
}</code></pre>
</div>


<p>out of the controller and moving it to the cell as</p>

<div>
  <pre><code class='objective-c'>- (void) updateForModelObject:(Model*)object 
{
   self.nameLabel.text = object.name;
   self.valueLabel.text = object.value;
}</code></pre>
</div>


<p>(Yes, he defines it as <code>-updateCell:forIndexPath:</code> but <code>-updateCell:forModelObject:</code> can always be refactored out of that once the object is found for the indexPath.)</p>

<p>There may be some additional smarts in there: The color of valueLabel may get changed at a threshold value, the name text may need some truncation or transformation, an icon may change from sun to moon depending on a timestamp in the object. I&rsquo;ve left them out of the example for simplicity.</p>

<p>At this simplistic level, they look identical. Yet I still feel putting the logic in the cell is superior. Why?</p>

<h1>Polymorphism</h1>

<p>Look a bit closer at <code>-updateCell:forModelObject:</code>. You may not even have noticed it, but there&rsquo;s a distinct absence of the keyword <code>self</code>. This isn&rsquo;t encapsulation; this method is really just a utility method, which could just as easily be written in C: </p>

<div>
  <pre><code class='objective-c'>void UpdateCellForModelObject( MyTableViewCell* cell, ModelObject* object );</code></pre>
</div>


<p>Why is this bad? It throws away polymorphism, one of my favorite aspects of object-oriented programming. Let&rsquo;s start with a theming example: We want to allow the user to chose between a set of differently-styled themes in which to display this homogeneous set of data.</p>

<p>This is fairly simple if it&rsquo;s limited to colors, fonts, and other style-only changes in the themes&mdash;change the style in <code>-tableView:cellForRowAtIndexPath:</code> and continue as before. What if one theme &ldquo;FirstLast&rdquo; should display my name as &ldquo;Paul Goracke&rdquo; and theme &ldquo;LastFirst&rdquo; should display as &ldquo;Goracke, Paul&rdquo;? The table view controller needs to know this difference. It&rsquo;s an implementation detail of the theme, but under this design the controller doesn&rsquo;t just need to know about it&mdash;it needs to <em>implement</em> it.</p>

<p>It will need to implement the quirks of <em>every</em> theme supported. Not bad enough for you? How about this: It also needs to determine which set of theme quirks to use <em>each and every invocation</em> of <code>-updateCell:forModelObject:</code>. Why would you want to do this? I don&rsquo;t.</p>

<p>By putting the logic in the cell, you only check the theme in <code>-tableView:cellForIndexPath:</code>.</p>

<ol>
<li><p> Dequeue or create a cell of the appropriate type <code>MyFirstLastTableViewCell</code> or <code>MyLastFirstTableViewCell</code>.</p></li>
<li><p> Call <code>-[cell updateForModelObject:]</code> and the receiver cell will update as appropriate for the single theme it implements.</p></li>
<li><p> There is no Step 3.</p></li>
</ol>


<p>This is the glory of polymorphism: No matter how many crazy themes I make, the table view controller only needs to know which class to make for the specified theme because the subclass knows its specific implementation. If I decide to sunset a theme, I don&rsquo;t have to worry about code cruft hanging about in the controller to handle that obsolete theme.</p>

<h1>Polymorphism with Heterogeneous Model Objects</h1>

<p>A heterogeneous data set in and of itself wouldn&rsquo;t be a problem as long as all objects provide the core set of properties the cell requires to display the items uniformly. (Such would be the case with Brent&rsquo;s Twitter app example.) Your cell(s) now take <code>-updateForModelObject:(id&lt;ModelObjectProtocol&gt;)</code>, they don&rsquo;t care which particular protocol implementor you pass them as long as they provide the properties needed to display them, and you move on.</p>

<p>But what of a heteregeneous set where each object type needs to display differently?</p>

<p>Once again, the logic of which cell subclass to create lies with <code>-tableView:cellForRowAtindexPath:</code>. After that, updating the cell&rsquo;s display of model object property changes is handled by the cell. If the model object at that indexPath were to change type, call <code>-reloadRowsAtIndexPaths:withRowAnimation:</code> on the table view to have it ask for a new or dequeued cell of the type appropriate for the model object&rsquo;s new type. </p>

<h1>What Makes a Controller a Controller?</h1>

<p>Unfortunately, Apple seems to have unintentionally muddied the MVC waters by naming their main controller class <code>UIViewController</code>. Many developers now have an extreme view of a controller: If it touches both a view and model object at all it needs to be a <code>UIViewController</code>. Nothing could be further from the truth. Unless you need lazy view loading and view appear/disappear lifecycle management, creating a <code>UIViewController</code> just overcomplicates matters.</p>

<p>Let&rsquo;s look at Apple&rsquo;s schematic of MVC, even though it should already be burned into every Cocoa and iOS developer&rsquo;s brain:</p>

<p><img src="http://corporationunknown.com/blog/images/2013/MVC2.png" alt="Model-View-Controller" /></p>

<p>It&rsquo;s easy to get caught up in defining these objects based on their positions in the diagram, but what really defines them is their <em>role</em> within the system and how updates propagate. Keep in mind that these arrows are not object references, but interactions via updates and notifications—think of them as IBActions more than IBOutlets.</p>

<p>When a <code>UITableViewCell</code> subclass accepts a model object parameter and updates its constituent subviews as I have described, it is behaving as a data transformer, <em>not</em> a controller. It does not care about any future updates to the model unless the <em>controller</em> tells it to transform the updated model object, or to transform a completely different model instance.</p>

<h1>Keys to Success</h1>

<ul>
<li><p>Avoid the temptation to bypass the controller and start key-value observing (notifications are also verboten) on the received model object. This is the hubris that will lead to your MVC downfall (been there, done that). Leave <em>all</em> of the updating logic to the &ldquo;true&rdquo; view controller, and your cell subclass will remain a happy and healthy data transformer.</p></li>
<li><p>Don&rsquo;t even keep a reference to the received model object. Not only will this help avoid the KVO temptation, but it will encourage you to quickly move the property values into the appropriate subviews and let them take care of drawing, caching and refreshing.</p></li>
<li><p>You&rsquo;re a UITableViewCell&mdash;you&rsquo;re displaying only one in a possibly innumerable collection of model objects. Leave the handling of the set of model objects to your <code>UIViewController&lt;UITableViewDataSource&gt;</code> which should be invoking tableView updates based on responding to <code>UIFetchedResultsController</code> or KVO, but there may be other update logic involved. That is, after all, the purpose of a controller.</p></li>
<li><p>Keep your cells stupid. Brent&rsquo;s examples of loading image or web service data asynchronously is still something to be avoided in the cell.</p></li>
<li><p>Keep your cells simple. Many developers try to handle all possible configurations of a cell in one. They have numerous views which are hidden or displayed based on some model object criteria, which leaves a number of unused outlets lying around; this becomes confusing and hard to maintain. Using polymorphic cell subclasses, you can dedicate one cell subclass to each distinct configuration, avoiding unused views and code maintenance overhead.</p></li>
</ul>


<h1>Conclusion</h1>

<p>There is absolutely nothing wrong with Brent&rsquo;s minimalist guidelines. They will serve you well in many situations. But once your code base gets more complicated, I think you&rsquo;ll be better served by not fearing better encapsulation of behaviors. Passing a model object to your cell is really only a venial sin.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Define "Success"]]></title>
    <link href="http://corporationunknown.com/blog/2012/02/20/define-success/"/>
    <updated>2012-02-20T21:47:59-08:00</updated>
    <id>http://corporationunknown.com/blog/2012/02/20/define-success</id>
    <content type="html"><![CDATA[<p>What comes to mind when I say the word &ldquo;success&rdquo;?</p>

<!-- more -->


<p>Everyone has their own definition: Advancing in one&rsquo;s career; saving enough to retire; finding a significant other with whom to build a happy, healthy family. Complicating matters further, &ldquo;success&rdquo; has much finer-grained contexts: Each successive day of kicking a bad habit; completing a project milestone; passing a test in school. Many &ldquo;personal improvement&rdquo; programs would even propose that &ldquo;success&rdquo; is only measurable as a continuing accumulation of completed milestones, not any one observable point in time.</p>

<p>So why in the world do you think you can capture &ldquo;success&rdquo; in a boolean?</p>

<div>
  <pre><code class='objective-c'>BOOL success = [self doSomething];</code></pre>
</div>


<p>That method you just called actually did something, and it did something concrete: It deleted (or saved) a file on disk; parsed some JSON; validated an encrypted string.</p>

<p>Don&rsquo;t try to capture success in a variable. Name your booleans for what the code actually accomplishes and you&rsquo;ll find the following logic is much more readable with a decreased likelihood of logic bugs.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Gotcher Address Book!]]></title>
    <link href="http://corporationunknown.com/blog/2012/02/09/gotcher-address-book/"/>
    <updated>2012-02-09T14:25:20-08:00</updated>
    <id>http://corporationunknown.com/blog/2012/02/09/gotcher-address-book</id>
    <content type="html"><![CDATA[<p>Even though I installed the Path app and set up an account, I never really used it. It never really clicked with me; I really only signed up because many people I know were trying/using it. So it wasn&rsquo;t anything close to a &ldquo;hardship&rdquo; for me to ask them to delete my account when it was <a href="http://mclov.in/2012/02/08/path-uploads-your-entire-address-book-to-their-servers.html">revealed that they were uploading the contents of my address book to their servers.</a> Still, I&rsquo;m disappointed.</p>

<p>Last fall, we were in the crunch-time week for a client&rsquo;s app before the iOS 5.0 submission deadline. I was profiling it in Instruments, trying to find where we could improve its launch-time performance, when I found a noticeable amount of time was spent in Address Book queries by a third-party video tracking library.</p>

<!-- more -->


<p>Not only was this behavior slowing down our launch, it was unexpected and&mdash;since it was a binary library without source code provided&mdash;we had no idea what it was doing with that information. A red flag was raised, and to my surprise the client even expressed willingness to cut the functionality until the questions could be answered.</p>

<p>As explained, the usage was almost clever: By adding a defined contact to your address book, you would unlock additional debug logging and reporting options for their SDK. They claimed that there were numerous applications already approved with this SDK, and I don&rsquo;t feel the need to question their veracity. Most importantly, they offered a build without that functionality, provided it quickly, and that&rsquo;s what shipped.</p>

<p>So it disappoints me that after my own personal experience of trying to keep code out of the Address Book, there are developers out there who apparently don&rsquo;t think twice about slurping all of your contacts and sending them to their servers without your express permission.</p>

<p>This has <a href="http://isource.com/2008/07/23/aurora-feint-removed-from-app-store-over-privacy-concerns-hopefully-to-return-soon/">happened before with Aurora Feint.</a> It forever tainted my opinion of Open Feint, which came out of that. I had been under the impression that Apple was much more strict about this type of behavior&mdash;&ldquo;chance of rejection&rdquo; was one of the main reasons I brought attention to the library&rsquo;s unexpected access. So I&rsquo;m disappointed in Apple, too.</p>

<p>There have been calls for Apple to add required guards and notifications to the API&rsquo;s access, similar to how Location Services is handled. That would probably be good, but at a certain point all the notifications just become &ldquo;Grant Access?&rdquo; alerts that users don&rsquo;t think about. I think there&rsquo;s a simpler way to do it, at least for a first attempt:</p>

<ol>
<li><p>When submitting an app to iTunes Connect, ask &ldquo;Do you access and transmit Address Book data?&rdquo; similar to the existing question about using encryption.</p></li>
<li><p>Answering &ldquo;yes&rdquo; is a flag to the review team to verify that the developers have implemented their own reasonable opt-in mechanism, and maybe even a bit more scrutiny of their network traffic.</p></li>
<li><p>If an app is found to be violating this, terminate the developer&rsquo;s account.</p></li>
</ol>


<p>Yes, I feel that violating this expectation after making it clear that you are expected to be transparent about using this kind of information is worthy of booting you out of the App Store.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Farewell, Steve Jobs]]></title>
    <link href="http://corporationunknown.com/blog/2011/10/05/farewell-steve-jobs/"/>
    <updated>2011-10-05T18:56:38-07:00</updated>
    <id>http://corporationunknown.com/blog/2011/10/05/farewell-steve-jobs</id>
    <content type="html"><![CDATA[<p>Few depart this world having left a piece of themselves in so many others. I shall cherish my tiny share.</p>

<p>Thank you, Mr. Jobs. Thank you, Jobs family, for sharing him with us.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to Fix Patents]]></title>
    <link href="http://corporationunknown.com/blog/2011/05/18/how-to-fix-patents/"/>
    <updated>2011-05-18T09:49:43-07:00</updated>
    <id>http://corporationunknown.com/blog/2011/05/18/how-to-fix-patents</id>
    <content type="html"><![CDATA[<p>As I understand it, the intent of a patent is to protect the value of the invention to the inventor by giving them exclusive control of the rights to use said invention. In return, they are asked to encourage future innovation by sharing that information with the world instead of keeping it a proprietary secret. Pretty simple and straightforward, and I really have a hard time disagreeing with that being a desirable goal.</p>

<p>Most of the complaints about the patent system being &ldquo;broken&rdquo; come down to a few points:</p>

<!-- more -->


<ol>
<li><p>The patent is not novel; it&rsquo;s an obvious method to anyone spending any mental effort on the problem space.</p></li>
<li><p>The patent is too broad; It could cover any number of possible techniques without taking a stand on one (or a handful). This usually seems to be done to get around the requirement of sharing the information, keeping aspects proprietary. One might also consider this related to &ldquo;not novel.&rdquo;</p></li>
<li><p>The inventor (or, usually, reassigned rights holder commonly referred to as &ldquo;patent troll&rdquo;) has done nothing with their rights to the patent on their own. On its own, there is nothing wrong with this&mdash;it would be perfectly legitimate to have a sole licensee. When combined with items 1 or 2, though, most people agree that it&rsquo;s is predatory and stifles innovation rather than encouraging it.</p></li>
</ol>


<p>My Proposal: Within a defined grace period after patent status is granted (I&rsquo;m envisioning 5 years, maybe 7), the patent holder must show measurable revenue due to a concrete implementation of the patent, or that it is a recognizable part of another product which generates recognizable revenue. This revenue may be recognized directly by the inventor, or by licensees of the patent. If such evidence is not given within the grace period, the patent is considered fallow and control rights are revoked.</p>

<p>A patent that does not result in a concrete implementation within a reasonable period of time is hard to consider as &ldquo;benefitting society&rdquo; and thus unworthy of the rights exclusivity granted by the society in exchange.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[It Lives!]]></title>
    <link href="http://corporationunknown.com/blog/2011/04/24/it-lives/"/>
    <updated>2011-04-24T17:35:51-07:00</updated>
    <id>http://corporationunknown.com/blog/2011/04/24/it-lives</id>
    <content type="html"><![CDATA[<p>(There is no Easter-related content here; the timing is pure coincidence.)</p>

<p>I just received word that the <a href="http://itunes.apple.com/us/app/espn-passport/id382744201?mt=8">2.0 update to ESPN Passport</a>&mdash;the last fruits of my contracting with the fine folks of <a href="http://www.roguesheep.com/">RogueSheep</a> before joining <a href="http://www.blackpixel.com/">Black Pixel</a>&mdash;went live on the App Store today. What started out as &ldquo;add Facebook Places functionality&rdquo; became a much smoother, more efficient and focused application that I was proud to have a part in.</p>

<p>If you&rsquo;re at all interested in adding a social network aspect to your sports watching, go check it out. It&rsquo;s free, but you&rsquo;ll need to sign up for a <a href="http://espn.go.com/travel/passport/">free ESPN Passport login</a> to get the most out of it (Facebook and Twitter logins add even more).</p>

<p><a href="http://itunes.apple.com/us/app/espn-passport/id382744201?mt=8"><img src="http://corporationunknown.com/blog/images/2011/passport.png" alt="Passport" /></a></p>

<p>(By the way, have you tried RogueSheep&rsquo;s latest app, <a href="http://www.roguesheep.com/easyalarms.html">Easy Alarms</a>? I played no part in it, but it rocks all the same.)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[You Got Your License in My Keychain!]]></title>
    <link href="http://corporationunknown.com/blog/2011/04/13/you-got-your-license-in-my-keychain/"/>
    <updated>2011-04-13T09:18:21-07:00</updated>
    <id>http://corporationunknown.com/blog/2011/04/13/you-got-your-license-in-my-keychain</id>
    <content type="html"><![CDATA[<p><em>The One In Which Paul Talks Out His Hat (metaphorically, since he and hats don&rsquo;t get along).</em></p>

<p>During an entertaining aside in <a href="http://ihnatko.com/">Andy Ihnatko</a>&rsquo;s keynote at this weekend&rsquo;s <a href="http://iphonespring2011.crowdvine.com/">Voices That Matter conference</a>, I was reminded of a thought I&rsquo;d had a while ago: Why don&rsquo;t Mac desktop applications store their license info in the <a href="http://developer.apple.com/library/ios/#documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html">Keychain</a>?</p>

<!-- more -->


<p>Complaining about restoring license keys should be just as trite of a humor topic as little bags of peanuts on flights, but it still holds true. Go to restore a machine, or move to a new one with a clean install, and you can write off at least an afternoon launching and entering at least two text fields per application.</p>

<p>Maybe I&rsquo;m the only one who feels quite comfortable with syncing to MobileMe&mdash;I actually consider it <em>the</em> feature that keeps me coming back. (I do know there are people who have frustrating issues, and I truly feel for them, but I continue to believe they are in the minority.) Given that setup, here&rsquo;s how I&rsquo;d see setting up a new laptop:</p>

<ol>
<li><p>Configure my MobileMe account and sync down the data, setting up my Mail accounts, Address Book and Calendar&mdash;and Keychain.</p></li>
<li><p>Launch a new copy of my licensed application.</p></li>
<li><p>There is no Step Three. Go on your merry way.</p></li>
</ol>


<p>I&rsquo;m not expert enough to suggest that it would improve security of your key, but it sure would discourage casual tweaking more than the plist or hidden file schemes you&rsquo;d need to develop on your own. Also, separation of license key from a preferences file (hopefully developers are already doing this) allows a user to delete the preferences and start fresh without having to worry about relicensing.</p>

<p>I understand that Keychain development can be convoluted, but is that reason enough to not make the user&rsquo;s life a little bit easier and your support burden of finding a lost license a little less frequent?</p>

<p>As I said at the top, I realize I&rsquo;m talking out of my&hellip;hat here. I don&rsquo;t have experience doing this (yet), so I am interested in hearing reasoned arguments. Until and unless this is proven untenable, simply consider it a feature request for your next release.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iPad and the Digital Hub, Revisited]]></title>
    <link href="http://corporationunknown.com/blog/2011/03/10/ipad-and-the-digital-hub-revisited/"/>
    <updated>2011-03-10T06:33:02-08:00</updated>
    <id>http://corporationunknown.com/blog/2011/03/10/ipad-and-the-digital-hub-revisited</id>
    <content type="html"><![CDATA[<p>Apple released iOS 4.3 yesterday, and it looks like <a href="http://www.appleinsider.com/articles/11/03/03/inside_ios_4_3_mobile_streaming_with_itunes_home_sharing.html">iTunes Home Sharing</a> provides almost everything I had wished for in <a href="http://corporationunknown.com/blog/2010/07/08/ipad-and-the-digital-hub/">my original post</a>.</p>

<p>There seem to be some quirks (all videos and podcasts are marked as unplayed on the device) and other behaviors I&rsquo;d like changed (watching/listening to a podcast on the device doesn&rsquo;t report that to the shared library). These niggles are really just small issues compared to the big advance of having access to my full library.</p>

<p>Thank you, iOS team!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Year in Review 2010]]></title>
    <link href="http://corporationunknown.com/blog/2011/01/11/year-in-review-2010/"/>
    <updated>2011-01-11T08:19:29-08:00</updated>
    <id>http://corporationunknown.com/blog/2011/01/11/year-in-review-2010</id>
    <content type="html"><![CDATA[<p>It&rsquo;s still the first half of January, so I&rsquo;m in the grace period for a &ldquo;Year in Review&rdquo; post.</p>

<p>2010 was one heck of a slingshot year for me and Corporation Unknown. I started the year unemployed and thin on contract work, and finished it with Corporation Unknown&rsquo;s highest revenue in its 3-year history and a job offer I can&rsquo;t refuse.</p>

<!-- more -->


<h1>Bankruptcy</h1>

<p>After starting out looking promising, 2009 was rough. The latter half was my first try at full-time independent contracting. I spent time working on project proposals where the client apparently went with someone willing to work for $25/hour; I did work on a decent project (iPhone client for the web site they were developing) that then went &ldquo;on hold&rdquo; once the company I was subcontracting for realized that <em>their</em> client was behind on payments to the tune of six digits. (They paid me in full, I don&rsquo;t know if they ever got the same.)</p>

<p>At the beginning of 2010, my wife and I filed for personal bankruptcy. This isn&rsquo;t something I&rsquo;m proud of, but I refuse to hide it as a personal shame. I debated even mentioning this here, except for two points I hope might be able to help others approaching a similar situation:</p>

<ol>
<li><p>Start looking into bankruptcy <em>before</em> dipping into retirement savings. Most likely, those funds are protected from the proceedings and you won&rsquo;t have to start over.</p></li>
<li><p>The idea of paying a lawyer $3k to file for bankruptcy seems <em>wrong</em>, doesn&rsquo;t it? It was completely worth it. Under our attorney&rsquo;s advice, we knew exactly what to expect with no surprises. Sometimes when trying to restart parts of your life, it&rsquo;s refreshing to just chuck it all and walk away, consequences be damned&mdash;this is not one of those times.</p></li>
</ol>


<h1>Contracting</h1>

<p>Independent contracting in 2010 was hot and cold. More accurately, cold then hot, and feast or famine. I&rsquo;d go without prospects for a while, then have a few come all at once that I actually had to choose from. Managing a client pipeline is not easy as a solo contractor.</p>

<p>In the spring, I had the opportunity to work with local friends <a href="http://blackpixel.com/">Black Pixel</a> on a small part of a fairly large project for iPad&mdash;before its release. It&rsquo;s hard to believe the iPad hasn&rsquo;t been out a full year yet; recalling having to code for iPad without a test device feels like reminiscing about the punchcard days.</p>

<p>I had a good time working on that project, even though it was all too brief. The team was wonderful, and even though it feels unfair, I have to single out the experience of working with Chris Clark. It was the first time I&rsquo;d had the opportunity to work on an iOS project with a dedicated designer&mdash;one who listens, takes feedback, and respectfully tells you you&rsquo;re either wrong, or he just prefers his design anyway&mdash;and I loved that.</p>

<p>At that time, I was also working on a project with a existing client. They had an iPhone app that I had cleaned up somewhat, and the announcement of iPad seemed an ideal fit for their product. Unfortunately, in the early days of the iPad, I still needed a lot of experimenting to get a feel for what &ldquo;worked&rdquo; and what didn&rsquo;t. In their desire to get in to the field as quick as possible, they felt that the project was taking too long and ended up opting out of the contract.</p>

<p>Then in May, I had the opportunity to do some subcontracting work for fellow locals <a href="http://www.roguesheep.com/">RogueSheep</a>. The project was for a component of an iPad app that, once I got past the &ldquo;why would you want to do that?&rdquo; aspect, provided some interesting challenges in designing custom controls and animations, and I loved that.</p>

<p>RogueSheep is another great team, and another great designer in Brad Ellis (even if he has since moved on to <a href="https://squareup.com/">Square</a>). Brad has the same positive qualities as Chris, with the addition of slightly crazier ideas that push you to create something you wouldn&rsquo;t have imagined on your own.</p>

<p>Thankfully, the Sheep have continued to have a project pipeline for me to work on: I wrote another bit of code that I&rsquo;m not even sure has made it onto the store yet for the same client; I wrote some UI code for RogueSheep&rsquo;s own <a href="http://touchup.roguesheep.com/">TouchUp for iPad</a> application as they were readying it for release, and I&rsquo;m in the process of finishing off another pretty major iPhone project for another of their clients. They even let me touch their Apple Design Award.</p>

<p>Thanks in large part to RogueSheep, in its first full year of full-time effort, Corporation Unknown has recorded its highest annual revenue:</p>

<p><img src="http://corporationunknown.com/blog/images/2011/CU-Revenue.png" alt="CU Revenue.png" /></p>

<h1>Onward</h1>

<p>This year already has some promising challenges ahead:</p>

<ol>
<li><p>Beginning in March, I will be teaching &ldquo;Developing with the iPhone SDK,&rdquo; the middle course of the iPhone and Cocoa Development certification from the University of Washington&rsquo;s Professional and Continuing Education.</p></li>
<li><p>I have accepted an offer to return to Black Pixel full-time beginning in February. It&rsquo;s been tough feeling like I&rsquo;m choosing between two great companies and teams, but I am really excited to be rejoining Black Pixel&rsquo;s now-expanded team and continuing to kick some iOS butt.</p></li>
<li><p>On top of all that, our second child is due at the end of July.</p></li>
</ol>


<p>2011 is going to be a busy year!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Bughunting a Bashful Table View]]></title>
    <link href="http://corporationunknown.com/blog/2010/12/14/bughunting-a-bashful-table-view/"/>
    <updated>2010-12-14T07:46:15-08:00</updated>
    <id>http://corporationunknown.com/blog/2010/12/14/bughunting-a-bashful-table-view</id>
    <content type="html"><![CDATA[<p>I ran down a strange bug yesterday that I thought I would recount in the hopes of saving someone else the half day of frustration.</p>

<p>I was going along, minding my own business, implementing a typical <code>-tableView:didSelectRowAtIndexPath:</code> delegate method to create a view controller, push it onto the navigation stack, and then&hellip;nothing. The view didn&rsquo;t appear, and the app interface became unresponsive. Numerous pauses in the debugger showed what would appear to be normal stacks in the running of the app&mdash;no infinite recursion going on, thankfully.</p>

<p>The view was actually in a strange nesting of <code>UITableViewControllers</code>, <code>UINavigationControllers</code> and <code>UITabBarControllers</code>, so I reworked that to the bare bones of a <code>UITableViewController</code> pushing a freshly made <code>UITableViewController</code> onto its navigationController. I verified that it was being initialized properly, and that I had a valid navigationController to push onto (and other view controllers did push with the same navigationController). Still no change.</p>

<!-- more -->


<p>Then I added breakpoints to every <code>UITableViewDelegate</code> and <code>DataSource</code> method I&rsquo;d implemented, even the trivial hardcoded ones (&ldquo;<code>return 3;</code>&rdquo; for <code>-numberOfSectionsInTableView:</code>) at first to ensure they were being called (they were). Thus began the tedium of following the chain of 4 or 5 calls per table row until I found the offending code.</p>

<p>This new table view is composed of a number of sections each composed of only one cell. The cells are designed in Interface Builder as top-level objects, and are IBOutlets of the File&rsquo;s Owner View Controller. Technically, it&rsquo;s one big scroll view but I&rsquo;m using this design to provide some layout flexibility if the client wants to reorganize sections, and I thought it would be cool to have the dynamic scrolling of section headers, too.</p>

<p>Since I want the IB objects to define the layout, I determine the height of each row based on the view&rsquo;s frame:</p>

<div>
  <pre><code class='objective-c'>height = CGRectGetHeight( self.playerStatsCell.frame );</code></pre>
</div>


<p>The value for height of this cell (the last on the list&mdash;the others were fine) was a &ldquo;whopping&rdquo; 6.30104785e-38. What was going on here?!</p>

<p>Well, <code>self.playerStatsCell</code> wasn&rsquo;t actually connected yet because I was testing (<em>trying</em> to test) one row/section at a time. Calling the frame method on a nil object seems like a normal thing to do in messaging-nil-happy Objective-C. But it&rsquo;s not. The call is effectively short-circuited, and the temporary <code>CGRect</code> variable the return value was supposed to fill is left uninitialized, which is the bizarre height value returned by <code>CGRectGetHeight</code>.</p>

<p>This call is equivalent to:</p>

<div>
  <pre><code class='objective-c'>CGRect frame; // uninitialized struct
frame = self.playerStatsCell.frame;
height = CGRectGetHeight( frame );</code></pre>
</div>


<p>A simple change to the following would fix it:</p>

<div>
  <pre><code class='objective-c'>CGRect frame = CGRectZero; // initialized struct
frame = self.playerStatsCell.frame;
height = CGRectGetHeight( frame );</code></pre>
</div>


<p>(In my case, I resolved it by connecting a temporary cell object in IB.)</p>

<p>What did I learn from this?</p>

<ol>
<li><p>Messaging to nil is normally fine, but definitely not for struct-returning methods.</p></li>
<li><p>Returning a cell height that is very, very tiny from <code>-tableView:heightForRowAtIndexPath:</code> results in &ldquo;strange behavior.&rdquo;</p></li>
</ol>


<p>I still don&rsquo;t know exactly what the app was doing while it <em>wasn&rsquo;t</em> displaying the new table view, but now I know what to quickly look for when I can&rsquo;t push a <code>UITableViewController</code> in the future.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sudden Termination]]></title>
    <link href="http://corporationunknown.com/blog/2010/10/30/sudden-termination/"/>
    <updated>2010-10-30T15:19:42-07:00</updated>
    <id>http://corporationunknown.com/blog/2010/10/30/sudden-termination</id>
    <content type="html"><![CDATA[<p>Today, <a href="http://www.tbray.org/ongoing/When/201x/2010/10/30/Three-Android-Software-Rules">Tim Bray commented</a> about Android applications needing to frequently save their restore state and be ready and able to gracefully terminate without notice. (This behavior also applies to iOS apps, of which I have much more experience than Android.)</p>

<blockquote><p>At some point, after I’d explained a few times why you have to write software this way on Android, I started wondering why all software, without exception, isn’t written this way by default.</p></blockquote>

<p>As of 10.6, Apple added <code>enableSuddenTermination</code> and <code>disableSuddenTermination</code> calls to the <a href="http://developer.apple.com/library/mac/releasenotes/MacOSX/WhatsNewInOSX/Articles/MacOSX10_6.html#//apple_ref/doc/uid/TP40008898-SW22">NSProcessInfo API</a> to allow you to implement similar behavior on the desktop.<!-- more --> At its most simplistic description, you can inform the system your application doesn&rsquo;t need to have its memory paged back in just to destroy it all&mdash;just kill the process and you will be sure it behaves properly on relaunch.</p>

<p>I encourage all fellow iOS developers who have already acquired a &ldquo;sudden termination&rdquo; design style to make note of this when developing a desktop Cocoa application; I also encourage desktop Cocoa developers to start thinking about how they would design with this paradigm, as it will be one more portable technique when and if you decide to go mobile.</p>

<p>(<a href="http://developer.apple.com/library/mac/#technotes/CachingPurgeableMemory/Introduction/Introduction.html">NSCache and Purgeable Memory</a> is another new-to-10.6 mechanism I consider similar to iOS&#8217; <code>didReceiveMemoryWarning</code>, only giving the OS permission to purge memory instead of it requesting you clean up.)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iPad and the Digital Hub]]></title>
    <link href="http://corporationunknown.com/blog/2010/07/08/ipad-and-the-digital-hub/"/>
    <updated>2010-07-08T11:46:50-07:00</updated>
    <id>http://corporationunknown.com/blog/2010/07/08/ipad-and-the-digital-hub</id>
    <content type="html"><![CDATA[<p><a href="https://twitter.com/pgor/status/17982503054">Yesterday I tweeted</a> about a feature I would like:</p>

<blockquote><p>Want: iPod on iPad able to browse desktop iTunes à la Home Sharing. Watching WWDC videos on iPad w/o having to sync first&mdash;yum.</p></blockquote>

<p>I received a few recommendations for <a href="http://www.inmethod.com/">Air Video</a> and <a href="http://projectswithlove.com/streamtome/">StreamToMe</a>. I&rsquo;d forgotten that I&rsquo;d downloaded Air Video but hadn&rsquo;t set up the server; I&rsquo;d also forgotten about StreamToMe even though I subscribe to Matt Gallagher&rsquo;s blog.</p>

<p>I fired up the Air Video Server and started it serving the iTunes U playlist. Connecting and browsing from the iPad client was simple and straightforward. Trying to stream a WWDC video paused to buffer annoyingly often&mdash;which I blame less on the software than the 2GHz Mini it was running on, which probably also had the misfortune to have Time Machine kick in at the same time. But it doesn&rsquo;t seem to have a functionality I implied by the &ldquo;Home Sharing&rdquo; reference: Copy the video to the iPad to watch elsewhere later. StreamToMe looks to have similar features (and lack thereof) to Air Video, so I didn&rsquo;t test it.</p>

<p>I appreciate the recommendations, I really do. But neither of these can get past the one requirement I didn&rsquo;t specify: I don&rsquo;t <em>want</em> a third-party solution. My tweet was really a passive-aggressive desire to have Apple implement this.</p>

<!-- more -->


<p>I have fully committed to iTunes being my central media repository. It serves 157GB of my music, 148GB of movies, 100GB of TV shows, 144GB of iTunes U videos (primarily WWDC videos) and a variable amount of audio and video podcasts. As a result, I don&rsquo;t have many files in formats foreign to iTunes, which both these applications seem focused on solving and I expect they handle admirably.</p>

<p>Both of my AppleTVs can access any file in the desktop&rsquo;s iTunes library, even though with 40GB and 160GB drives they obviously can&rsquo;t hold copies of everything. (True, I can&rsquo;t instruct an AppleTV to copy files to itself, but I don&rsquo;t feel the desire to pick it up and take it elsewhere, either.)</p>

<p>My iPad cannot access all the files.</p>

<p>My laptop can browse any file on the desktop&rsquo;s iTunes library; thanks to Home Sharing it can copy any file just by dragging it to the local library. It can even browse other libraries that are shared on the network.</p>

<p>My iPad cannot copy files to its local library, or browse other shared libraries.</p>

<p>The &ldquo;digital plumbing&rdquo; is there in DAAP and Home Sharing to make this happen, but third party developers are left to write their own servers to support their clients. I have no reason to distrust InMethod or Matt Gallagher&mdash;and I&rsquo;m pretty sure that either of them can write a better server than I ever could&mdash;but each additional server increases the likelihood of conflicts and security problems, so I don&rsquo;t <em>want</em> to install and maintain additional, practically redundant servers.</p>

<p>I <em>want</em> a digital hub; one machine serving the same media in different ways is not a hub.</p>

<p>During the iPad announcement, Steve Jobs positioned the iPad as a third type of device &ldquo;between a laptop and a smartphone.&rdquo; In my experience, that&rsquo;s an astute description. In regards to media handling, though, I feel the iPad still behaves much more like my iPhone than my MacBook Pro.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My Accessorizer Configuration]]></title>
    <link href="http://corporationunknown.com/blog/2010/06/27/my-accessorizer-configuration/"/>
    <updated>2010-06-27T12:52:28-07:00</updated>
    <id>http://corporationunknown.com/blog/2010/06/27/my-accessorizer-configuration</id>
    <content type="html"><![CDATA[<p>Due to &ldquo;overwhelming demand,&rdquo; I am sharing my configuration set for Accessorizer here. I think there needs to be some explanation to many of the decisions, though, so here you go. This is not intended to be an interminable discussion of coding style and practices, though&mdash;if you disagree, go ahead and make your own configuration based on mine. This is also not intended as comprehensive documentation for Accessorizer&mdash;read its included documentation, explore tooltips, and experiment freely.</p>

<!-- more -->


<blockquote><p>Download the <a href="http://corporationunknown.com/download/CorporationUnknown.azcf_.zip">Corporation Unknown configuration</a> for Accessorizer.</p></blockquote>

<p>At a previous employer, we ran into issues where newcomers were confused by Objective-C&rsquo;s memory management, especially the differences between using properties (and dot notation) and directly accessing the ivar. As you might expect, this led to many memory-related problems. I&rsquo;ve long been a proponent of only using accessors to access a member unless you have a darn good reason. (And Cocoa&#8217;s ? automatic key-value observing makes it even more difficult to have a good reason not to.) In order to visibly identify accessor-vs-direct access, we instituted a naming convention to make <a href="http://www.joelonsoftware.com/articles/Wrong.html">direct access look wrong</a>: ivars are named with an underscore prefix (&ldquo;_ivar&rdquo;) and properties are not. To make this even more obvious that ivars are implementation details, we declared them @private.</p>

<p>You may disagree with this methodology; that&rsquo;s fine. But without this context, you might have a hard time understanding my configuration decisions&mdash;and why Accessorizer especially rocks in this setup.</p>

<p>When I first started using Accessorizer, I thought of it as a code generator, and it&rsquo;s hard not to chafe at your disagreements with how code generators generate code. I&rsquo;ve found that thinking of it as a code <em>template</em> generator makes it easier: Generate the majority of stuff you use, omit the stuff you don&rsquo;t normally use, and be comfortable with the knowledge that you will regularly have to tweak its output&mdash;it&rsquo;s still better than writing it from scratch every time.</p>

<h1>Accessor Style</h1>

<p><img src="http://corporationunknown.com/blog/images/2010/Accessorizer-Properties.png" alt="Accessorizer Properties" /></p>

<ul>
<li><p>&ldquo;ObjC 2.0 Properties&rdquo; is always turned on. Period.</p></li>
<li><p>I always use the Defaults Table (more about that later).</p></li>
<li><p>&ldquo;Detect IBOutlets&rdquo; automatically inserts the &ldquo;IBOutlet&rdquo; declaration into recognized subclasses. Sometimes it doesn&rsquo;t identify a class I want to be an IBOutlet, but I find this to be right much more often than it is wrong.</p></li>
<li><p>&ldquo;Append self.view=nil&rdquo; is a somewhat strangely worded option. Checking it will generate code to nil those properties identified as IBOutlets. Combined with the &ldquo;&ndash;(void)viewDidUnload&rdquo; checkbox to its right, it will generate a full viewDidUnload method to release your IBOutlets.</p></li>
<li><p>&ldquo;Assign delegates&rdquo; automatically overrides your assign/retain/copy property generation setting to be &ldquo;assign&rdquo; for any &ldquo;id&rdquo; property (or others identified as a delegate form; again, I find more often right than wrong).</p></li>
<li><p>I uncheck &ldquo;Omit assign for scalars&rdquo;. True, the &ldquo;assign&rdquo; is not necessary, but I find it easier to scan for &ldquo;assign&rdquo; when I&rsquo;m code reviewing than have to think about each type and whether it is handled appropriately. (According to Apple&rsquo;s documentation, &ldquo;assign&rdquo; is also required for garbage collection but I haven&rsquo;t written any GC code yet.)</p></li>
<li><p>&ldquo;Assign IBOutlets&rdquo; is unchecked. I guess I&rsquo;m still in the &ldquo;retain outlets&rdquo; camp, until I bother to change my mind.</p></li>
<li><p>&ldquo;BOOL getter=isValue&rdquo; automatically identifies a &ldquo;BOOL running&rdquo; property and defines the getter as &ldquo;isRunning&rdquo;, just as Apple recommends.</p></li>
</ul>


<p><img src="http://corporationunknown.com/blog/images/2010/AccessorizerProps2.png" alt="Accessorizer Properties 2" /></p>

<ul>
<li><p>Since I&rsquo;ve primarily been coding for iOS lately, I declare my properties &ldquo;nonatomic&rdquo;. If/when you&rsquo;re working on the desktop, you probably want &ldquo;omit this&rdquo;&mdash;change it or create a &ldquo;desktop&rdquo; configuration.</p></li>
<li><p>I omit readonly/readwrite. Most of the readonly properties I create are not backed by ivars, so I find I don&rsquo;t need to override this behavior often.</p></li>
<li><p>I haven&rsquo;t been much concerned about <strong>weak or </strong>strong, so I omit it. You may decide otherwise.</p></li>
<li><p>&ldquo;@synthesize&rdquo; will create appropriate @synthesize statements when generation the Implementation. (Be sure to check &ldquo;generate getter/setter&rdquo;, even though it applies to @dynamic&mdash;I&rsquo;ll explain later when talking about Defaults Table.)</p></li>
</ul>


<h2>Getter/Setter settings</h2>

<p><img src="http://corporationunknown.com/blog/images/2010/AccessorizerGetterSetter.png" alt="Accessorizer Getters and Setters" /></p>

<p>Not much to say about these settings other than &ldquo;Use Defaults Table&rdquo;. They don&rsquo;t come into play very often, since I mainly use @synthesized properties but these settings work for me when I don&rsquo;t. To see the effects on generated code, temporarily switch your properties generation to @dynamic with &ldquo;generate getter/setter&rdquo; checked and Implementation being generated&mdash;changes will be reflected as you make them.</p>

<h2>Dealloc</h2>

<p><img src="http://corporationunknown.com/blog/images/2010/AccessorizerDealloc.png" alt="Accessorizer Dealloc" /></p>

<ul>
<li><p>I default to &ldquo;self.property = nil&rdquo; behavior; I know others disagree. If you&rsquo;re one of them, simply change the option to &ldquo;release&rdquo; in your configuration. If you do agree, or simply want to give this way a try, make a point of removing any related KVO or NSNotification observers before these generated lines or you will receive notifications of the nil settings and you most likely don&rsquo;t want that.</p></li>
<li><p>&ldquo;dealloc full block&rdquo; is the primary reason I am not just making my configuration available without comment. If you were to just take my configuration and copy the generated code, it would break your build because I leave this deselected so it&rsquo;s not in a code block. As I develop my classes, I add ivars and use Accessorizer to generate the related code. Most of the code is pretty easy to wholesale copy-n-paste, but I tend to have more logic in dealloc than Accessorizer can know about (KVO and NSNotification removal, setting delegates to nil, etc.) and I find it easier to copy this generated dealloc code into an existing method than to use this as a dealloc method and move existing behaviors into it. If you want a full dealloc method, just check the box.</p></li>
</ul>


<h2>Init and Undo</h2>

<p>I&rsquo;m not sure why, but I still tend to write my own init methods. Someday I&rsquo;ll explore using Accessorizer for this and Undo registration more fully; until then, you&rsquo;re on your own.</p>

<h1>Defaults Table</h1>

<p>The defaults table is used to override the &ldquo;one size fits all&rdquo; property generation based on the ivar&rsquo;s type. I have configured every superclass of &ldquo;NSMutable<Something>&rdquo; to default to &ldquo;copy&rdquo; instead of the default &ldquo;retain&rdquo; in order to avoid holding reference to a mutable object when I&rsquo;m expecting immutable. (This is explained in <a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW27">Apple&rsquo;s documentation</a>.) I don&rsquo;t even use some of these classes, but when I do I don&rsquo;t want to be surprised. I&rsquo;m always free to edit the declaration on a case-by-case basis, but this is the behavior I want ninety-some percent of the time.</p>

<p>Another fun feature of the Defaults Table is the &ldquo;generation&rdquo; setting. If you have a class type whose behavior you tend to override often, define its generation as &ldquo;dynamic&rdquo;. Every time you use that class type, Accessorizer will generate an @dynamic declaration&mdash;and the accessor methods for you to use as a starting template. (This is why I check the &ldquo;generate getter/setter&rdquo; in the Accessor tab even though it normally won&rsquo;t do anything.)</p>

<h1>Custom Table</h1>

<p>I don&rsquo;t really use this tab, and I don&rsquo;t believe any of it gets saved into a configuration set since it&rsquo;s primarily for point-and-click tweaking of behavior on an ivar-by-ivar basis.</p>

<h1>Coding Style</h1>

<p><img src="http://corporationunknown.com/blog/images/2010/AccessorizerCodingStyle.png" alt="Accessorizer ivar Prefix and Suffix" /></p>

<p>As I mentioned, I prefix my ivars with an underscore, so here is where I define that. By defining my ivar Prefix as &ldquo;_&rdquo; and Suffix as &ldquo;none&rdquo;, Accessorizer automatically recognizes that underscore and strips it when declaring the property. It also properly declares the backing ivar in the @synthesize directive.</p>

<ul>
<li><p>The Argument Prefix is used when generating methods like -initWith{&hellip;}. I vacillate between &ldquo;a&rdquo; and &ldquo;none&rdquo;.</p></li>
<li><p>Formatting Properties: new to 2.0 is the ability to tweak whitespace in declarations more than you could in previous versions. I&rsquo;m happy because now I can use my preferred &ldquo;NSString* title&rdquo; form; I know many others still hew to the &ldquo;asterisk must bind the the variable, not type&rdquo; but you&rsquo;re free to change it for yourself.</p></li>
<li><p>Formatting Methods: Configure the display to generate some accessor methods and experiment with these settings to see which layout you prefer. The &ldquo;Tight&rdquo; spacing option is actually more compressed than I like, but I find the &ldquo;Spaced&rdquo; option way too spread out (and I&rsquo;m someone who loves whitespace). Therefore, I default to &ldquo;Tight&rdquo; because it&rsquo;s easier to insert the few spaces I prefer than delete all the ones I don&rsquo;t.</p></li>
<li><p>Formatting Pragma Marks: I love me some pragma marks, but try not to go overboard with them. Feel free to experiment.</p></li>
<li><p>Init Style: Apparently, &ldquo;self = [super init]&rdquo; is the current Apple-approved format. I&rsquo;m ambivalent.</p></li>
</ul>


<h1>Collection Accessors, Keyed Archiving, KVO, Locking, Singleton, General and Sort</h1>

<p>Most of these tabs are more hands-on generation of code. You need to enter a class name, and it will generate code right there&mdash;I don&rsquo;t use these as frequently as accessor generation, and you can tweak the layout more directly when you do need it. At some point, I may have changed my settings from the defaults you would encounter in a new install, but I don&rsquo;t really have strong suggestions for you here.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Accessorizer 2.0 Configuration Sets]]></title>
    <link href="http://corporationunknown.com/blog/2010/05/31/accessorizer-2-0-configuration-sets/"/>
    <updated>2010-05-31T19:26:00-07:00</updated>
    <id>http://corporationunknown.com/blog/2010/05/31/accessorizer-2-0-configuration-sets</id>
    <content type="html"><![CDATA[<p>The new version of <a href="http://www.kevincallahan.org/software/accessorizer.html">Accessorizer</a> is out! I&rsquo;m still amazed at how many Cocoa (including iPhoneOS) developers I encounter who don&rsquo;t know of this awesome utility. Here are just a few things this app does:</p>

<!-- more -->


<ol>
<li><p>As its name suggests, it will generate the getters and setters for ivars you point it at. It will do this using Objective-C 2.0 @property syntax if you specify it. (I use the 2.0 syntax and revert when I want to customize a getter or setter so i can start with a &ldquo;standard&rdquo; usage style.)</p></li>
<li><p>Automatically recognize UIKit and AppKit classes and mark the properties as IBOutlets.</p></li>
<li><p>Recognize non-object ivars and set their properties as &ldquo;assign&rdquo; instead of &ldquo;retain&rdquo;.</p></li>
<li><p>You can configure defaults for ivar classes (all my NSString and NSData properties default to &ldquo;copy&rdquo; instead of &ldquo;retain&rdquo;).</p></li>
<li><p>Generate all the methods for collections to be nicely Key-Value Observing compliant.</p></li>
<li><p>Generate Keyed Archiving and Unarchiving methods for your ivars.</p></li>
<li><p>Generate template code for a Singleton class.</p></li>
</ol>


<p>That&rsquo;s really just scratching the surface, but it&rsquo;s the main functionality I use. As a Cocoa developer, you truly do owe it to yourself to check it out.</p>

<p>What makes me (rather selfishly) consider 2.0 an awesome update, though, is a feature I requested: Configuration Sets. The request grew partly out of encountering co-workers at contracting gigs who didn&rsquo;t use Accessorizer. There are so many items to customize in the application, a first use could be daunting. If I can say, &ldquo;Here&rsquo;s my configuration to get you started,&rdquo; and pass along my exported Configuration, they&rsquo;re more likely to use it. (It also helps that they can now feel confident that they can revert after experimenting with settings.)</p>

<p>If I&rsquo;m working on multiple projects with multiple clients, I can save their specific formatting requirements and switch between Configuration Sets when I change between projects.</p>

<p>If your company has defined formatting standards for the aspects Accessorizer can generate, standardizing with a Configuration Set allows you to quickly bring a new team member up to speed and into compliance.</p>

<p>There are more aspects to Configuration Sets I&rsquo;d like to see, but they fall on the &ldquo;magical&rdquo; end of the spectrum; Kevin has done a great job of implementing the (more than) 80% part of it.</p>

<p>Seriously: Why aren&rsquo;t you using Accessorizer?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[WWDC: Eat the Lunch]]></title>
    <link href="http://corporationunknown.com/blog/2010/05/20/wwdc-eat-the-lunch/"/>
    <updated>2010-05-20T09:33:15-07:00</updated>
    <id>http://corporationunknown.com/blog/2010/05/20/wwdc-eat-the-lunch</id>
    <content type="html"><![CDATA[<p>&lsquo;Tis the season for WWDC Survival Guides. I don&rsquo;t really have anything to add from <a href="http://corporationunknown.com/blog/2009/06/04/prepping-for-wwdc/">my post last year</a>, but I want to state an opinion contrary to the prevailing common wisdom: Don&rsquo;t be afraid to eat the lunches.</p>

<!-- more -->


<p>Digression: C4 is/was known for its excellent sit-down meals between sessions. At first, it seemed horribly inefficient to an engineer brain to get up after a session, move &ldquo;all the way&rdquo; to the banquet room next door, have to pick out a seat again, only to return to the session hall and have to find a new seat&mdash;why not just leave my stuff camped in the same seat all day?</p>

<p>But I quickly heeded Wolf&rsquo;s advice-slash-admonition to find a different group of people to sit with at each change&mdash;and the world opened up. If you went to C4 just for the tech sessions, it was worth the cost but you only got the tip of the iceberg. I met well-knowns and unknowns and learned about their products, their consulting and business development experience, and got to know them without pressure. I may not even remember their names right now (I&rsquo;m terrible with names) but every one of those conversations built community.</p>

<p>I&rsquo;m not going to claim WWDC lunches will ever approach C4&rsquo;s, but you can incorporate a bit of the C4 experience into WWDC: Instead of getting together with the same group for lunch every day, take at least two lunches in the cafeteria area. Find a seat at a table with other people you don&rsquo;t know, and strike up a conversation to find out who they are, what they do, where they&rsquo;re from. I somewhat unintentionally did this last year, and I promise you: It will open your eyes.</p>

<p>If you&rsquo;re stuck for icebreakers, here are some old reliables:</p>

<ul>
<li><p>&ldquo;What did you think of the Keynote/&lsquo;State of&rsquo; addresses?&rdquo;</p></li>
<li><p>&ldquo;Did you catch yesterday&rsquo;s Brown Bag session?&rdquo;</p></li>
<li><p>&ldquo;What sessions are you looking forward to?&rdquo; (earlier in the week)</p></li>
<li><p>&ldquo;What was the best session you attended?&rdquo; (I love this one later in the week)</p></li>
</ul>


<p>Asking where someone&rsquo;s from or how many WWDCs they&rsquo;ve attended tend to be short answers that don&rsquo;t lead to conversations. Asking about shipping software can be great&mdash;people love talking about their products&mdash;but make the interest genuine so it doesn&rsquo;t feel like an interview or &ldquo;I&rsquo;m only asking about yours so I can tell you about mine.&rdquo;</p>

<p>Bring your business cards. After or during an interesting discussion, ask for one of theirs and offer one of yours. Periodically review the cards you&rsquo;ve received during the week to refresh your memory of names and topics&mdash;you&rsquo;ll be surprised how often you&rsquo;ll run into those same people later.</p>

<p>Keep your own badge visible as much as possible to make it easy to approach you and ask about your company or just say &ldquo;your name sounds familiar, did you&hellip;?&rdquo;</p>

<p>For more advice on networking, check out <a href="http://inessential.com/2010/02/10/advice_to_new_developers_on_networking">Brent Simmon&rsquo;s &ldquo;Advice to new developers on networking&rdquo;</a>.</p>

<p>For more tips on WWDC, <a href="http://iphonedevelopment.blogspot.com/2010/04/wwdc-first-time-guide-2010-edition.html">Jeff LaMarche&rsquo;s &ldquo;First Time Guide&rdquo;</a> contains nothing but tips I completely agree with. (Except my serious personal aversion to sleeping in public, including on planes.) Wait, I have one extra note: Plan to stow your gear before attending the Thursday Bash. I had my laptop backpack one year, and was miserable.</p>
]]></content>
  </entry>
  
</feed>
