<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>I’m the co-founder of Meridian Apps and Spotlight Mobile.

@nfarina/ twitter



  var _gaq = _gaq || [];
  _gaq.push([‘_setAccount’, ‘UA-139239-11’]);
  _gaq.push([‘_trackPageview’]);

  (function() {
    var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
    ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
    (document.getElementsByTagName(‘head’)[0] || document.getElementsByTagName(‘body’)[0]).appendChild(ga);
  })();</description><title>Nick Farina</title><generator>Tumblr (3.0; @nfarina)</generator><link>http://nfarina.com/</link><item><title>Feeds</title><description>&lt;p style="text-align:center"&gt;
    &lt;img src="http://cl.ly/3x17231T0h1d123y0c2b/application%20icon.png"/&gt;&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an app I whipped up with the help of designer &lt;a href="http://eric.grossnickle.org/"&gt;Eric Grossnickle&lt;/a&gt;. It has one purpose: to live in your Mac menubar and notify you when things happen on your favorite sites. That&amp;#8217;s pretty much it.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/3k2K2P101t420g2k3V2G/Screen%20Shot%202012-01-24%20at%208.28.41%20AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;You also get a little menubar app with your notification history, read/unread status, and popover content previews (Lion only).&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/0N3k1Q2F1g1m2l3M2I3F/Image%202012.01.24%208:39:55%20AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;It currently supports &lt;a href="http://dribbble.com/"&gt;Dribbble&lt;/a&gt;, &lt;a href="http://basecamphq.com/"&gt;Basecamp&lt;/a&gt;, &lt;a href="http://highrisehq.com/"&gt;Highrise&lt;/a&gt;, &lt;a href="http://github.com/"&gt;Github&lt;/a&gt;, &lt;a href="http://beanstalkapp.com/"&gt;Beanstalk&lt;/a&gt;, &lt;a href="http://trello.com/"&gt;Trello&lt;/a&gt;, and &lt;a href="http://uservoice.com/"&gt;UserVoice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you would like us to support a particular service, &lt;a href="http://feedsapp.uservoice.com/"&gt;cast a vote&lt;/a&gt; in our UserVoice forum!&lt;/p&gt;</description><link>http://nfarina.com/post/18148755036</link><guid>http://nfarina.com/post/18148755036</guid><pubDate>Thu, 23 Feb 2012 14:06:00 -0800</pubDate></item><item><title>Why Indoor Navigation is so Hard</title><description>&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/423j2p1Y3R1A1d380b40/Image_2011.10.12_12_11_53_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;I wrote a piece for &lt;a href="http://radar.oreilly.com"&gt;Radar&lt;/a&gt; about our company&amp;#8217;s approach to indoor navigation with mobile apps.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Remember the days before you could pull your smartphone out of your pocket and get instant directions from your current location to anywhere in the world? It&amp;#8217;s kind of foggy for me, too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://radar.oreilly.com/2011/10/indoor-navigation.html"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/11362278100</link><guid>http://nfarina.com/post/11362278100</guid><pubDate>Wed, 12 Oct 2011 12:13:00 -0700</pubDate></item><item><title>Git Is Simpler Than You Think</title><description>&lt;p&gt;It was about one year ago that we switched to Git. Previously, we used Subversion, through the Mac app &lt;a href="http://versionsapp.com"&gt;Versions&lt;/a&gt;, which (rightly) holds an Apple Design Award.&lt;/p&gt;

&lt;p style="text-align:center;position:relative;left:-20px;"&gt;
    &lt;img src="http://cl.ly/1w3c282U1I34073u0W3D/screen2.png"/&gt;&lt;/p&gt;

&lt;p&gt;I made the executive decision to leave our comfy world of Versions because it seemed clear that Git was winning the Internet. There was much grumbling from my teammates, who were busy enough doing actual work thank you very much.&lt;/p&gt;

&lt;p&gt;But I pressed forward. We signed up for accounts on &lt;a href="http://github.com"&gt;Github&lt;/a&gt;. We learned how to type &lt;code&gt;'git push'&lt;/code&gt; and &lt;code&gt;'git pull'&lt;/code&gt;. We became more confident. Git is just like any other source control system! But it wasn&amp;#8217;t long before one of our devs called me over to look at a…situation.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p style="text-align:center;position:relative;left:-30px;margin-bottom:-20px;"&gt;
    &lt;img src="http://cl.ly/3V0F0u1t1v3S2I3q3e3F/Screen_Shot_2011-09-04_at_10.44.51_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;It might as well have printed &lt;a href="http://en.wikipedia.org/wiki/PC_LOAD_LETTER"&gt;PC LOAD LETTER&lt;/a&gt;. &amp;#8220;Falling back to patching base and 3-way merge?&amp;#8221; That does not sound good &lt;em&gt;at all&lt;/em&gt;. Or maybe it&amp;#8217;s completely normal? I type &lt;code&gt;'git status'&lt;/code&gt;.&lt;/p&gt;

&lt;p style="text-align:center;position:relative;left:-30px;margin-bottom:-20px;"&gt;
    &lt;img src="http://cl.ly/3t1a281s3S0g0q1V1j07/Screen_Shot_2011-09-04_at_10.54.12_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;&amp;#8220;Not currently on any branch?!&amp;#8221; Now I&amp;#8217;ve done it. We&amp;#8217;re going to lose all the work he did today. Sweat is beading up on my forehead. Everyone is watching me to see if I can figure this out. After all, I got us into this mess.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#maintenance" name="maintenance"&gt;Maintenance Required&lt;/a&gt;&lt;/h2&gt;

&lt;p style="text-align:center;position:relative;left:-60px;margin-top:30px;margin-bottom:25px;"&gt;
    &lt;img src="http://cl.ly/2s2z3F0F2R183r222b29/ModelTFord1917sm.png"/&gt;&lt;/p&gt;

&lt;p&gt;Git is not a Prius. Git is a Model T. Its plumbing and wiring sticks out all over the place. You have to be a mechanic to operate it successfully or you&amp;#8217;ll be stuck on the side of the road when it breaks down. And it &lt;strong&gt;will&lt;/strong&gt; break down.&lt;/p&gt;

&lt;p&gt;By now we all know how to drive Git. We learned it by typing &amp;#8220;git tutorial&amp;#8221; into Google. We studied guides, how-tos, cheat sheets.&lt;/p&gt;

&lt;p&gt;Did you know the top result for &amp;#8220;git tutorial&amp;#8221; is &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html"&gt;this manpage&lt;/a&gt; on kernel.org? I will give you a gold star if you can read the whole thing without falling asleep.&lt;/p&gt;

&lt;p&gt;So instead let&amp;#8217;s pull over, open the hood up, and poke around.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#basics" name="basics"&gt;The Basics&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;ll run through some basic commands to make a repository for our examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~$ mkdir mysite
~$ cd mysite
~/mysite$ echo "&amp;lt;title&amp;gt;All About Cats&amp;lt;/title&amp;gt;" &amp;gt; index.html
~/mysite$ git init
~/mysite$ git add index.html
~/mysite$ git commit -m "First commit, added a title."
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have a git repository with one file and one &lt;em&gt;commit&lt;/em&gt;, that is to say, one &amp;#8220;version&amp;#8221;. Let&amp;#8217;s make a change and commit a second &amp;#8220;version&amp;#8221;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~/mysite$ echo "&amp;lt;center&amp;gt;Cats are cute.&amp;lt;/center&amp;gt;" &amp;gt;&amp;gt; index.html
~/mysite$ git commit -a -m "Added some text."
~/mysite$ open index.html 
&lt;/code&gt;&lt;/pre&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" style="margin-top: 20px; margin-bottom: 10px;" src="http://cl.ly/1p1t3s2a193w2Z193l0U/Untitled-2.png"/&gt;&lt;/p&gt;

&lt;p&gt;With me so far? Good.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#repository" name="repository"&gt;The Repository&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;In Git there is no &amp;#8220;client&amp;#8221; and &amp;#8220;server&amp;#8221;. A repository is a repository, no matter if it&amp;#8217;s on my machine, your machine, or Github.com.&lt;/p&gt;

&lt;p&gt;Each repository lives in a single hidden folder called &lt;code&gt;.git&lt;/code&gt;. This is in stark contrast to Subversion which infects your source tree with little &lt;code&gt;.svn&lt;/code&gt; folders everywhere.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img style="margin:7px;margin-top:11px;" src="http://cl.ly/462l3n1g2e1l3B3n450X/Untitled-2.png"/&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.git&lt;/code&gt; &amp;#8220;repository&amp;#8221; is more than just metadata and bookkeeping. It&amp;#8217;s &lt;em&gt;everything&lt;/em&gt;. All of your source, all your changes, all your branches, all your commit notes with swear words and in-jokes.&lt;/p&gt;

&lt;p&gt;Go ahead, delete your &lt;code&gt;index.html&lt;/code&gt;. As long as your &lt;code&gt;.git&lt;/code&gt; folder is intact, you can reconstruct it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~/mysite$ rm index.html
~/mysite$ git checkout -- .
~/mysite$ ls
index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That would work even if you&amp;#8217;d deleted a bunch of subfolders and huge files and whatever. Poof, it&amp;#8217;s all back.&lt;/p&gt;

&lt;p&gt;This explains why, when you &amp;#8220;checkout&amp;#8221; (&lt;em&gt;clone&lt;/em&gt;) the &lt;a href="https://github.com/rails/rails"&gt;Ruby on Rails&lt;/a&gt; repository from Github, it takes a surprisingly long time. You&amp;#8217;re downloading onto your machine, into your new &lt;code&gt;rails/.git&lt;/code&gt; folder, the entire history of Ruby on Rails. Every tiny change from David&amp;#8217;s &lt;a href="https://github.com/rails/rails/commit/db045dbbf60b53dbe013ef25554fd013baf88134"&gt;initial commit&lt;/a&gt; in 2004, it&amp;#8217;s all sitting there on your disk.&lt;/p&gt;

&lt;p&gt;This troubled me &lt;em&gt;greatly&lt;/em&gt; at first. It&amp;#8217;s so inefficient! My precious disk space!&lt;/p&gt;

&lt;p&gt;And I can only say that disk space turned out to be a non-issue. But it took me some time. Maybe go take a walk outside, look at some trees, and come back later when you&amp;#8217;ve accepted it.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" style="margin: 20px;" src="http://cl.ly/1y212d1k3M1W0t040009/IMG_0594.png"/&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#ui" name="ui"&gt;User Interface&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Now if you&amp;#8217;re a curious person, you&amp;#8217;ll likely say &amp;#8220;Wait. Go back. Where did you get the line &amp;#8216;&lt;code&gt;git checkout -- .&lt;/code&gt;&amp;#8217; from? What does that even &lt;em&gt;mean&lt;/em&gt;?&amp;#8221;&lt;/p&gt;

&lt;p&gt;To which I&amp;#8217;ll respond, &amp;#8220;I don&amp;#8217;t know. I Googled it.&amp;#8221;&lt;/p&gt;

&lt;p&gt;And this brings us to Git&amp;#8217;s greatest shortcoming, which is that &lt;strong&gt;Git&amp;#8217;s terminology and syntax is fracking inscrutable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Git&amp;#8217;s overloaded, confusing language is absolutely the only part of it that sucks. They meant well. They chose words that sound familiar, like &lt;em&gt;branch&lt;/em&gt;, &lt;em&gt;checkout&lt;/em&gt;, &lt;em&gt;tag&lt;/em&gt;, &lt;em&gt;merge&lt;/em&gt;. But they often mean different things. Then you get the feeling that, as features were added and rethought, they just picked new unused words as they went along. &lt;em&gt;Stage&lt;/em&gt;, &lt;em&gt;fetch&lt;/em&gt;, &lt;em&gt;rebase&lt;/em&gt;, &lt;em&gt;remotes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And because of Git&amp;#8217;s explosive popularity, it&amp;#8217;s a total Emperor-Has-No-Clothes situation. If you&amp;#8217;re anything like me, you probably wondered why you were the only stupid person on the planet who didn&amp;#8217;t intuitively get Git already. Even the beloved Github, though unaffiliated with Git, is much the same: as overwhelming as it is awesome.&lt;/p&gt;

&lt;p style="text-align:center; position:relative; left: -75px;"&gt;
    &lt;img class="framed" style="margin:20px;" src="http://cl.ly/3v3N453Q051R2n183q3x/Untitled-1.png"/&gt;&lt;/p&gt;

&lt;p&gt;Ultimately, when you look at Git, you don&amp;#8217;t see a product that was &amp;#8220;designed&amp;#8221; holistically. It&amp;#8217;s more like a collection of command-line utilities.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#commandline" name="commandline"&gt;A Collection of Command-Line Utilities&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;This is a much better way to think about Git, and in fact this is what Git originally &lt;em&gt;was&lt;/em&gt;. Git started life as a &lt;a href="http://lkml.org/lkml/2005/4/6/121"&gt;week-long project&lt;/a&gt; of Linus Torvalds to replace the &lt;a href="http://www.bitkeeper.com/"&gt;old version control system&lt;/a&gt; they were using at the time to manage contributions to the Linux kernel.&lt;/p&gt;

&lt;p&gt;You can&amp;#8217;t design and build a fully-featured distributed version control system in a week. But you &lt;em&gt;can&lt;/em&gt; design your data model. And it had better be really, really simple.&lt;/p&gt;

&lt;p&gt;So what&amp;#8217;s Git&amp;#8217;s data model? To answer that, we need to dig into that mysterious &lt;code&gt;.git&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#objects" name="objects"&gt;The So-Called &amp;#8220;Object Database&amp;#8221;&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;mysite/.git&lt;/code&gt;, there is a subfolder called &lt;code&gt;objects&lt;/code&gt;. It should contain these folders and files (edited for clarity):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~/mysite $ find .
./index.html
./.git
./.git/objects
./.git/objects/0d/0321f29f04f734e8d9873e34d9409fe115b496
./.git/objects/23/581023e9850ab48ec5ea6c4c9dcbeb82e76461
./.git/objects/2d/48a74575acab21d702f17f4ecce126b7e34ab0
./.git/objects/5b/853962ae2f41f608428968f8fffbf72f6cec2b
./.git/objects/87/48d7719d7321fad3739fce87ff84b6ded47e8b
./.git/objects/b1/a701e38645a3e60bc17a786cdd9062a15b5a21
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These files with mangled-looking names are the &amp;#8220;objects&amp;#8221; in our database for &lt;code&gt;mysite&lt;/code&gt;. An object can be either a &lt;em&gt;commit&lt;/em&gt;, a &lt;em&gt;tree&lt;/em&gt;, a &lt;em&gt;blob&lt;/em&gt;, or a &lt;em&gt;tag&lt;/em&gt;. They&amp;#8217;re compressed with zlib, but you can &lt;a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/ch08.html"&gt;extract and examine them easily&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If we were to extract the object &lt;code&gt;23/5810…&lt;/code&gt;, we would see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;title&amp;gt;All About Cats&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…which is the old version of &lt;code&gt;index.html&lt;/code&gt;! So that&amp;#8217;s a &lt;em&gt;blob&lt;/em&gt;, that is, a particular version of one file. If we extract the object &lt;code&gt;0d/0321…&lt;/code&gt;, we get:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;commit 227tree 5b853962ae2f41f608428968f8fffbf72f6cec2b
parent b1a701e38645a3e60bc17a786cdd9062a15b5a21
author Nick Farina &amp;lt;n...@gmail.com&amp;gt; 1315106589 -0700
committer Nick Farina &amp;lt;n...@gmail.com&amp;gt; 1315106589 -0700

Added some text.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…which is a &lt;em&gt;commit&lt;/em&gt; object (our last commit).&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re following along, you&amp;#8217;ll notice that you don&amp;#8217;t have an object &lt;code&gt;0d/0321&lt;/code&gt;. Your commit will have a different mangled name because your author name and email won&amp;#8217;t match mine. You see, the &amp;#8220;mangled names&amp;#8221; of these files are &lt;a href="http://en.wikipedia.org/wiki/SHA-1#The_SHA-1_hash_function"&gt;SHA1 Hashes&lt;/a&gt; of their contents. If we computed the hash of the blob &lt;code&gt;&amp;lt;title&amp;gt;All About Cats&amp;lt;/title&amp;gt;&lt;/code&gt;, we&amp;#8217;d get:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;23581023e9850ab48ec5ea6c4c9dcbeb82e76461
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Recognize that hash from the &lt;code&gt;23/5810…&lt;/code&gt; filename above? Git chops off the first 2 characters of the hash and uses that as a directory name, so we don&amp;#8217;t end up with too many of these little files in one place.&lt;/p&gt;

&lt;p&gt;Git calls this &amp;#8220;content-addressable&amp;#8221; to sound fancy, but really it&amp;#8217;s just a naming scheme. See, these &amp;#8220;objects&amp;#8221; have to be called &lt;em&gt;something&lt;/em&gt;, so they might as well be named according to their contents.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#sha1" name="sha1"&gt;Content-Addressable&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Now if you&amp;#8217;re reasonably paranoid, you may ask: &amp;#8220;What if two different objects compute the same SHA1 hash code? Won&amp;#8217;t this happen someday?&amp;#8221;&lt;/p&gt;

&lt;p&gt;It turns out you&amp;#8217;ll never generate two of the same SHA1 hashes. The chances are miniscule. There&amp;#8217;s room for all kinds of flowery comparisons like: You&amp;#8217;d have to generate more hash codes than the number of stars in the universe before you&amp;#8217;d get two of the same!&lt;/p&gt;

&lt;p&gt;But my favorite is from &lt;a href="http://progit.org/book/ch6-1.html"&gt;Pro Git&lt;/a&gt;: &amp;#8220;A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night.&amp;#8221;&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" style="margin:20px;" src="http://cl.ly/012n2u190D0B3a0n2Q09/stars2.png"/&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#commits" name="commits"&gt;Commits&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;commit&lt;/em&gt; represents a complete version of your code. Look again at the object file representing our last commit:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;commit 227tree 5b853962ae2f41f608428968f8fffbf72f6cec2b
parent b1a701e38645a3e60bc17a786cdd9062a15b5a21
author Nick Farina &amp;lt;n...@gmail.com&amp;gt; 1315106589 -0700
committer Nick Farina &amp;lt;n...@gmail.com&amp;gt; 1315106589 -0700

Added some text.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This chunk of text contains enough hints to reconstruct the entire contents and history of our repository as it existed in this version.&lt;/p&gt;

&lt;p&gt;The hash &lt;code&gt;5b8539…&lt;/code&gt; is the object containing the state of our &lt;em&gt;tree&lt;/em&gt;. A tree object is basically a manifest of files and folders (simplified here):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;blob 2d48a74575acab21d702f17f4ecce126b7e34ab0  index.html
blob b8ca7d5cba87d5123182375871234a76d6f78ff2  someotherfile.html  &amp;lt;- example 2nd blob
tree 3182375871234a76d6f78ff2b8ca7d5cba87d512  Documentation       &amp;lt;- example subfolder
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This represents the filesystem structure at this point in time. Cleverly, subfolders are represented by pointers to &lt;em&gt;other&lt;/em&gt; tree objects. Recursion! The &amp;#8220;blob objects&amp;#8221; then contain the actual file data like &lt;code&gt;&amp;lt;title&amp;gt;All About Cats&amp;lt;/title&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get the previous version of our repository, look at the &amp;#8220;parent&amp;#8221; hash beginning with &lt;code&gt;b1a701&lt;/code&gt; (again, different for you). This is the object containing the &lt;em&gt;previous&lt;/em&gt; commit.&lt;/p&gt;

&lt;p&gt;So just by starting with our last commit object, we&amp;#8217;ve explored the entire contents of our repository.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#branches" name="branches"&gt;Branches&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;If we had a thousand objects in our database, it would be pretty hard to guess the hash of our last commit. So we&amp;#8217;d better write it down somewhere.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~/mysite$ cat .git/refs/heads/master
0d0321f29f04f734e8d9873e34d9409fe115b496
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is what a &lt;em&gt;branch&lt;/em&gt; is: it&amp;#8217;s simply the hash of the last commit scribbled down in a file. It&amp;#8217;s a clue, a starting point, sometimes called a &lt;em&gt;tip&lt;/em&gt; because this represents the tip of the iceberg that is the entire history of the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;And since you can have multiple branches in a repository, we should also remember which one we&amp;#8217;re working on right now.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;~/mysite$ cat .git/HEAD
ref: refs/heads/master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s forehead-slapping simple. Whenever you execute a Git command, it first looks at &lt;code&gt;.git/HEAD&lt;/code&gt; to see what our working copy is &lt;em&gt;supposed&lt;/em&gt; to be. And that contains a reference to either a branch name or a commit object (that case is a &lt;em&gt;detached HEAD&lt;/em&gt;). If it&amp;#8217;s a branch name, look at the branch file to see what commit object it is. Then open up the commit object to find all the trees and blobs and parents and it&amp;#8217;s &lt;a href="http://evolvingthoughts.net/2011/03/turtles-all-the-way-down/"&gt;turtles all the way down&lt;/a&gt;.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/0H3F0N320C3K3B1V3z3d/turtles-all-the-way-down.png"/&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#uniqueness" name="uniqueness"&gt;Uniqueness&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;One last thing to ponder. Our &lt;code&gt;objects&lt;/code&gt; folder contains 6 files. Three for the first version&amp;#8217;s commit object, tree, and blob. And three again for the last version&amp;#8217;s commit object, tree, and blob.&lt;/p&gt;

&lt;p&gt;If you zipped up your entire &lt;code&gt;mysite&lt;/code&gt; folder right now and emailed it to me, I could unzip it and make another change to &lt;code&gt;index.html&lt;/code&gt; and commit that change to my local copy on disk. Let&amp;#8217;s say I changed the line to say &lt;code&gt;&amp;lt;center&amp;gt;Cats are TERRIBLY cute.&amp;lt;/center&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now I have 9 files in my &lt;code&gt;objects&lt;/code&gt; folder. Three more for the commit I just made, its tree and blob.&lt;/p&gt;

&lt;p&gt;I want to share my changes with you. So I zip up the 3 object files you don&amp;#8217;t have and email them to you.&lt;/p&gt;

&lt;p&gt;Are you ready for this? You take my three object files and just dump them into your &lt;code&gt;objects&lt;/code&gt; folder. You don&amp;#8217;t have to worry &lt;em&gt;at all&lt;/em&gt; about overwriting anything, about losing data, about &lt;em&gt;screwing up&lt;/em&gt; your repository, because we&amp;#8217;ve already established that these file names are &lt;strong&gt;completely unique&lt;/strong&gt;. Wolves in the night, remember?&lt;/p&gt;

&lt;p&gt;You&amp;#8217;ve just manually performed a &lt;code&gt;git fetch&lt;/code&gt;, which is the safest operation ever because it&amp;#8217;s just collecting someone else&amp;#8217;s unique commit files and tossing them into to your database.&lt;/p&gt;

&lt;p&gt;In my email, I&amp;#8217;ll say &amp;#8220;My latest commit is &lt;code&gt;3bd54c&lt;/code&gt;.&amp;#8221; So you type &amp;#8220;&lt;code&gt;git checkout 3bd54c&lt;/code&gt;&amp;#8221; and &lt;em&gt;boom&lt;/em&gt; you&amp;#8217;re looking at my latest changes.&lt;/p&gt;

&lt;p&gt;If we emailed back and forth a lot, I might want to add you as a &lt;em&gt;remote&lt;/em&gt; so that Git does the moving of files around for me. And I might scribble down the latest commit hash that I got from you in a file called &lt;code&gt;origin/master&lt;/code&gt; or something. Sound familiar?&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#mastery" name="mastery"&gt;Mastery&lt;/a&gt;&lt;/h2&gt;

&lt;p style="text-align:center"&gt;
    &lt;a href="http://octodex.github.com/#octobiwan"&gt;
        &lt;img style="margin-bottom:-10px" src="http://cl.ly/3C0E011o143H0x0P1Y10/octobiwan.png"/&gt;&lt;/a&gt;
    &lt;br/&gt;&lt;span style="color: #888; font-size:80%"&gt;&lt;em&gt;Octobi Wan Catnobi&lt;/em&gt; by&lt;/span&gt;
    &lt;a href="https://github.com/cameronmcefee"&gt;
        &lt;img style="width:18px;height:18px;position:relative;top:5px;border:1px solid #ccc;" src="https://secure.gravatar.com/avatar/a79ff2bb7da84e275361857d2feb2b1b?s=140&amp;amp;d=https://d3nwyuy0nl342s.cloudfront.net%2Fimages%2Fgravatars%2Fgravatar-140.png"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;For me, understanding the structure of the object database was my Eureka moment for Git. After that, I could start to understand not just how Git worked, but &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The best way to get yourself out of a Git disaster scenario is to understand what Git is trying to do for you.&lt;/p&gt;

&lt;p&gt;And when you understand how Git works, your Google Power will increase tenfold. How did I know to type &amp;#8220;&lt;code&gt;git checkout -- .&lt;/code&gt;&amp;#8221;? Well I just looked online until I found a command that sounded like it did what &lt;em&gt;I would do myself&lt;/em&gt; if I had to write some code to poke around the object database.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s a lot more to grok about Git from here. Merging, rebasing, and staging come to mind. But it&amp;#8217;s not so hard now; it&amp;#8217;s all just a bunch of fancy shell scripts anyway.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
    pre { color: #555; font-size: 90%; margin-left: 20px; margin-bottom:20px; }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/9868516270</link><guid>http://nfarina.com/post/9868516270</guid><pubDate>Wed, 07 Sep 2011 09:23:00 -0700</pubDate></item><item><title>An iOS Developer Takes on Android</title><description>&lt;p style="text-align:center"&gt;
    &lt;img src="http://cl.ly/34182G3F1r1L2r0K1M0N/Untitled-1.png" style="margin-right: 16px; margin-bottom: -20px;"/&gt;&lt;/p&gt;

&lt;p&gt;Recently, we released the &lt;a href="https://market.android.com/details?id=meridian.app"&gt;Android version&lt;/a&gt; of &lt;a href="http://www.meridianapps.com"&gt;Meridian&lt;/a&gt;, our platform for building location-based apps.&lt;/p&gt;

&lt;p&gt;We didn&amp;#8217;t use one of these &amp;#8220;Cross Platform!&amp;#8221; tools like &lt;a href="http://www.appcelerator.com"&gt;Titanium&lt;/a&gt;. We wrote it, from scratch, in Java, like you do in Android.&lt;/p&gt;

&lt;p&gt;We decided it was important to keep the native stuff native, and to respect each platform&amp;#8217;s conventions as much as possible. Some conventions are easy to follow, like putting our tabs on the top. Other conventions go deep into the Android Way, like handling &lt;code&gt;Intents&lt;/code&gt;, closing old &lt;code&gt;Activities&lt;/code&gt;, implementing Search Providers, and being strict about references to help the garbage collector.&lt;/p&gt;

&lt;p&gt;Now, our platform leverages HTML5 (buzzword, sorry) in many places for branding and content display, so we got a fair amount of UI for free. But there was much platform code written in Objective-C that needed translation into Java, such as map navigation, directions, and location switching.&lt;/p&gt;

&lt;p&gt;So, we rolled up our sleeves, downloaded the Android SDK, and got to work.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2&gt;&lt;a style="color:black" href="#environment" name="environment"&gt;Development Environment&lt;/a&gt;&lt;/h2&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/003x0t3b1e430w3S2R0H/Screen_Shot_2011-07-29_at_1.07.18_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Apple has made it pretty easy to start writing iOS apps. Of course, Step One is &amp;#8220;Buy a Mac.&amp;#8221; Easy! Then just download the free Xcode Installer from the Mac App Store, and start writing code when it&amp;#8217;s done.&lt;/p&gt;

&lt;p&gt;Android is a bit more involved. You can &lt;a href="http://developer.android.com/sdk/index.html"&gt;download the SDK&lt;/a&gt; easily, but to actually start writing code, you&amp;#8217;ll want to setup &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; and install Google&amp;#8217;s &lt;a href="http://developer.android.com/sdk/eclipse-adt.html"&gt;ADT Plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to waste a week or so playing around and not getting work done, you could explore the many tempting alternatives to writing Java in Eclipse. You could download &lt;a href="http://netbeans.org/"&gt;Netbeans&lt;/a&gt;, or write in &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;, or finally start learning &lt;a href="http://www.vim.org/"&gt;VIM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But let&amp;#8217;s assume you are on a deadline and want to do things the way that Google endorses. The first thing you&amp;#8217;ll need to do is accept the reality of Eclipse.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img style="margin-bottom: -15px" src="http://cl.ly/1E1t0n292k0q1c2f1v0x/Screen_Shot_2011-07-29_at_1.02.42_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;You&amp;#8217;re going to just &lt;em&gt;hate&lt;/em&gt; Eclipse. You&amp;#8217;re going to hate it with the heat of a thousand suns. It&amp;#8217;s going to feel slow and bloated and it won&amp;#8217;t &lt;a href="http://www.joelonsoftware.com/articles/LordPalmerston.html"&gt;taste like real food&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Eclipse is a world unto itself. It&amp;#8217;s the IDE to end IDEs. Consequently, it has many abstract-sounding concepts you&amp;#8217;ll have to learn. There are &lt;em&gt;Workspaces&lt;/em&gt;, and &lt;em&gt;Perspectives&lt;/em&gt;, and &lt;em&gt;Run Configurations&lt;/em&gt;.  And Eclipse itself is just an empty shell of sorts; all non-trivial functionality is provided via a complex network of interdependent &lt;em&gt;Plugins&lt;/em&gt;, similar to Linux distributions. Come to think of it…&lt;/p&gt;

&lt;p&gt;Of course, IDE weirdness isn&amp;#8217;t unique to Eclipse; Xcode was pretty damn weird at first too, and it&amp;#8217;s getting more &lt;em&gt;meta&lt;/em&gt; with each release (&lt;em&gt;Schemes&lt;/em&gt;, anyone?).&lt;/p&gt;

&lt;p&gt;The upside is, after acclimating to Eclipse, you&amp;#8217;ll enjoy some seriously amazing, productivity-boosting code completion, refactoring, and automatic fixing. It&amp;#8217;ll basically write your code for you.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img src="http://cl.ly/2R3b0w0f3G1F16271V2C/Image_2011.07.29_7_46_41_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;A great way to get comfortable with Eclipse is to spend a couple hours, and I&amp;#8217;m being dead serious, tweaking the hundreds of options and checkboxes and fiddly things in the Preferences section.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/1x3E2f0V320d2n1f0V3e/Screen_Shot_2011-07-29_at_1.29.14_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Again, being serious here, I felt a lot more comfortable and familiar and happy with Eclipse after getting to know it this way. Does this mean that other programs should expose every conceivable preference imaginable? Jesus, no. Are you crazy?&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#java" name="java"&gt;The Java Language&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Java is a high level programming language. It&amp;#8217;s unproductive to have an opinion about it. Instead, consider how Android &lt;em&gt;uses&lt;/em&gt; Java.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developer.android.com/reference/android/os/AsyncTask.html"&gt;This&lt;/a&gt; is how you do something on a background thread. &lt;a href="http://developer.android.com/guide/topics/ui/ui-events.html"&gt;This&lt;/a&gt; is how you listen for events (it&amp;#8217;s actually just like a &lt;code&gt;delegate&lt;/code&gt; in ObjC). &lt;a href="http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle"&gt;This&lt;/a&gt; explains the lifecycle of &lt;code&gt;Activities&lt;/code&gt;, which are exactly like &lt;code&gt;UIViewControllers&lt;/code&gt; in Cocoa.&lt;/p&gt;

&lt;p&gt;Overall, the Android frameworks are very well designed and consistent, and the API works harmoniously with the Java language. It&amp;#8217;s actually similar enough in the fundamentals that our app has almost the &lt;em&gt;exact&lt;/em&gt; same class structure on Android as on iOS.&lt;/p&gt;

&lt;p&gt;And the code ended up looking strikingly similar as well. Here&amp;#8217;s a snippet of ObjC from our app that draws an arrowhead. Hover your mouse over it to see the Java version.&lt;/p&gt;

&lt;div style="position:relative; width:576px; height: 246px; border: 1px solid #ccc; margin-left:-40px;"&gt;
    &lt;img style="position:absolute;top:0;left:0;" src="http://cl.ly/2r201M2O1Y1J3F1c1V0R/Untitled-3.png"/&gt;&lt;img class="java" style="position:absolute;top:0;left:0;" src="http://cl.ly/1G2V3r3K230a1U3r471C/Untitled-3.png"/&gt;&lt;/div&gt;

&lt;p&gt;&lt;style&gt;
    .java { opacity:0; }
    .java:hover { opacity:1; }
&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;Freaky, right? A lot of our source is like that.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#debugging" name="debugging"&gt;Debugging&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Now that you&amp;#8217;ve written some code, you&amp;#8217;ll want to try running it. In Apple&amp;#8217;s world, we have the iOS &amp;#8220;Simulator.&amp;#8221;&lt;/p&gt;

&lt;p style="text-align:center; margin-top: -10px; margin-bottom: -20px;"&gt;
    &lt;img src="http://cl.ly/3W2X2g1Y1C2t463S0n3i/Screen_Shot_2011-07-30_at_9.16.09_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s called a Simulator because it&amp;#8217;s phony (ha!). It&amp;#8217;s not the real iPhone OS. When you run your app &amp;#8220;in the simulator,&amp;#8221; Xcode compiles your app into a &lt;em&gt;desktop&lt;/em&gt; application, and runs it natively on your Mac. If you look in Activity Monitor, you&amp;#8217;ll see your app right there, running alongside Mail and iCal and iTunes.&lt;/p&gt;

&lt;p&gt;The downside to the Simulator is that it doesn&amp;#8217;t exactly replicate the iOS environment. And your code isn&amp;#8217;t the same either; it must be compiled for x86/64 instead of ARM, so there&amp;#8217;s no guarantee things will work the same on an iOS device.&lt;/p&gt;

&lt;p&gt;The upside to the Simulator is that it&amp;#8217;s not an &amp;#8220;Emulator.&amp;#8221; What&amp;#8217;s an Emulator?&lt;/p&gt;

&lt;p style="text-align:center; margin-top: -10px; margin-bottom: -10px;"&gt;
    &lt;img src="http://cl.ly/1A1W2Z3d3A3t222e0W3t/Screen_Shot_2011-07-30_at_8.55.00_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Behold, the Android Emulator. Its goal is noble: to run your app on the complete unaltered Android OS inside a &lt;em&gt;virtual machine&lt;/em&gt; that executes ARM instructions.&lt;/p&gt;

&lt;p&gt;What is the primary quality of the Android Emulator?&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/292f3w2k0Y382H330Y2j/Screen_Shot_2011-07-30_at_9.39.45_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;I thought the iPhone Simulator was a terrible idea when I first heard of it, until I remembered that we built the &lt;em&gt;exact same thing&lt;/em&gt; for Windows Mobile back in the day, because the Windows Mobile Emulator was so &lt;em&gt;goddamn&lt;/em&gt; slow.&lt;/p&gt;

&lt;p&gt;It takes the Android Emulator ~2 minutes to boot up on my perfectly-modern machine. But what really hurts is the edit/debug cycle. Every time I change a bit of Java and need to rerun the app, it takes about 30 seconds to redeploy and start up in the Emulator. Compare that to 5 seconds on the iOS Simulator. It may not sound like much but remember you&amp;#8217;ll be doing this &lt;em&gt;hundreds&lt;/em&gt; of times throughout your day.&lt;/p&gt;

&lt;p&gt;Fortunately, it turns out to be much quicker to deploy and boot up your app on a physical device over USB. So trust me, just go out and &lt;a href="http://stackoverflow.com/questions/1968170/can-i-tweak-my-android-emulator-to-make-it-fast"&gt;buy an Android phone&lt;/a&gt;. Better: buy a few of them to test against &lt;a href="http://stackoverflow.com/questions/2539074/which-android-phone-to-use-for-development"&gt;fragmentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not that fragmentation is unique to Android; it&amp;#8217;s just exaggerated a lot in the media. We need quite a few iOS devices in our lab too. One tiny unexpected OS or device difference can bring your app crashing down, on &lt;em&gt;any&lt;/em&gt; platform.&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#ui" name="ui"&gt;UI Design Tools&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;For laying out widgets on iOS, we have Interface Builder.&lt;/p&gt;

&lt;p style="text-align:center; margin-left: -40px; margin-bottom: -5px"&gt;
    &lt;img src="http://cl.ly/1F222K000R0e1f2S2J1U/Screen_Shot_2011-07-30_at_1.14.38_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Your experience with Interface Builder may differ from mine, but I&amp;#8217;ve learned to use it very sparingly. It&amp;#8217;s great when you want to create static layouts with precision. But for dynamic content, especially &lt;code&gt;UITableViews&lt;/code&gt;, it tends to make things &lt;em&gt;more&lt;/em&gt; complex than they would be in code. Especially when you come back after a while and forget all the little dependencies between your &lt;code&gt;Controller&lt;/code&gt; and your &lt;code&gt;XIB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On Android, you can create UI layouts in XML.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2v2Y0e2w280s1u2d450U/Screen_Shot_2011-07-30_at_1.28.40_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a bit like HTML, except it&amp;#8217;s &lt;em&gt;not&lt;/em&gt; HTML. It has a basic styling system that&amp;#8217;s kind of like CSS, except it&amp;#8217;s &lt;em&gt;not&lt;/em&gt; CSS.&lt;/p&gt;

&lt;p&gt;Lots of well-meaning developers in positions of power have tried to reinvent HTML and CSS over the years. Mozilla created &lt;a href="https://developer.mozilla.org/En/XUL"&gt;XUL&lt;/a&gt; for cross-platform UI in Firefox. Adobe created &lt;a href="http://learn.adobe.com/wiki/display/Flex/MXML"&gt;MXML&lt;/a&gt; for Flash. Microsoft created &lt;a href="http://msdn.microsoft.com/en-us/library/ms752059.aspx"&gt;XAML&lt;/a&gt; for Windows.&lt;/p&gt;

&lt;p&gt;I myself am guilty of creating my own XML-based layout system for Flash called &lt;a href="http://code.google.com/p/bent/"&gt;Bent&lt;/a&gt;, back when I had too much free time. So I can tell you that inventing these systems is the most fun you will ever have as a developer. It feels like you are creating the One True Framework, and once it&amp;#8217;s complete everyone will embrace it and get excited about it and learn it and build on it, and hold you up and sing epic poems about your genius!&lt;/p&gt;

&lt;p&gt;But the reality is, it&amp;#8217;s not HTML and CSS and so it&amp;#8217;s another thick layer of stuff that you have to learn and understand and fight with when things don&amp;#8217;t work like you expect.&lt;/p&gt;

&lt;p&gt;On the plus side, you can preview your XML at design-time in a nice visual editor, much like Interface Builder:&lt;/p&gt;

&lt;p style="text-align:center; margin-left: -40px; margin-bottom: -5px"&gt;
    &lt;img src="http://cl.ly/1H132f2e391r1J1W3E3M/Screen_Shot_2011-07-30_at_1.15.20_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Which is pretty grand.&lt;/p&gt;

&lt;p&gt;Now, technically you could write everything in Java, just like on iOS you can eschew Interface Builder entirely and write only Objective-C. But you&amp;#8217;ll find that when you scour the Internet for how to do a thing on Android, you&amp;#8217;ll end up needing to understand all these XML formats anyway just to understand code samples on the web.&lt;/p&gt;

&lt;p&gt;But it&amp;#8217;s not really that bad, because you also get…&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#boxmodel" name="boxmodel"&gt;A Real Box Model&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Here&amp;#8217;s a list item on iOS that represents a search result.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/3x0v3d032x1e1V3j1W0q/Image_2011.07.30_2_16_16_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;And here&amp;#8217;s just a snippet of the ObjC that renders that item:&lt;/p&gt;

&lt;p&gt;&lt;img style="margin-left:10px; margin-top: -10px;" src="http://cl.ly/2l0d122T3J301q3X2Q1x/Image_2011.07.30_2_11_00_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Talk about a bag of hurt. You could create the initial layout in Interface Builder of course, but then you&amp;#8217;d have to kiss that &lt;a href="http://blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview/"&gt;silky smooth scrolling&lt;/a&gt; goodbye. Maybe in the future when iOS devices are blazing fast.&lt;/p&gt;

&lt;p&gt;As humans, we don&amp;#8217;t typically think &amp;#8220;The title should be positioned at 30 pixels by 40 pixels, with a maximum height of 35 pixels.&amp;#8221; Instead, we think &amp;#8220;The title should be above the subtitle, and to the right of the thumbnail image, and have at most 2 lines.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Android has a system of layout containers (similar to HTML) that let you describe where content should be, relative to everything else. Here&amp;#8217;s a similar snippet from the same search result in Android:&lt;/p&gt;

&lt;p&gt;&lt;img style="margin-left:10px; margin-top: -10px;" src="http://cl.ly/2S2Z1N3Q3E2i3c3Z2y41/Screen_Shot_2011-07-30_at_2.30.47_PM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Now, you&amp;#8217;ll have to study up on all these layout containers like &lt;code&gt;FrameLayout&lt;/code&gt;, &lt;code&gt;LinearLayout&lt;/code&gt;, &lt;code&gt;RelativeLayout&lt;/code&gt;, and learn all their quirks, but in the end you&amp;#8217;ll get a very natural, flexible UI layout system.&lt;/p&gt;

&lt;p&gt;The best part is that it&amp;#8217;s zero-effort-easy to make layouts that automatically resize for portrait/landscape device orientations and varying screen sizes. This is in stark contrast to the absolutely primitive &lt;a href="http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW5"&gt;springs and struts&lt;/a&gt; system in Cocoa/iOS.&lt;/p&gt;

&lt;p&gt;But here&amp;#8217;s the thing about the simplistic layout system in iOS that I just mocked, it turns out to be a reasonable compromise when you consider…&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#animation" name="animation"&gt;Animation&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;The thing to realize about Android is that it used to look like this:&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/473T0j3M1Q3M2V3X3M3o/android02.png"/&gt;&lt;/p&gt;

&lt;p&gt;It was conceived and designed during the pre-iPhone days of Blackberry and Windows Mobile, and the influence of those platforms goes very deep into the Android OS.&lt;/p&gt;

&lt;p&gt;For instance. The rendering system, that is, the method by which UI widgets like menus and buttons and such get painted on the screen, is primarily software-based.&lt;/p&gt;

&lt;p&gt;What does that mean? Let&amp;#8217;s take the screenshot above as an example. If you pressed the Down key, you would expect the &amp;#8220;Homepage&amp;#8221; entry to be selected instead of &amp;#8220;Go to.&amp;#8221; So you press the Down key. This causes an &amp;#8220;invalidate,&amp;#8221; meaning, &amp;#8220;please repaint the screen.&amp;#8221; So the screen is cleared, then:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;The OS redraws the status bar at the top&lt;/li&gt;
&lt;li&gt;The WebView redraws the Google.com website&lt;/li&gt;
&lt;li&gt;The Menu draws its translucent black background and border&lt;/li&gt;
&lt;li&gt;All the menu text is drawn&lt;/li&gt;
&lt;li&gt;The blue gradient highlight is drawn over &amp;#8220;Homepage.&amp;#8221;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;This all happens very quickly, and you only ever see the final result, so it looks like just a few pixels have changed, but in fact the whole screen must be reconsidered and redrawn.&lt;/p&gt;

&lt;p&gt;If this sounds familiar, it&amp;#8217;s because this is the basic method used in &lt;a href="http://en.wikipedia.org/wiki/Graphics_Device_Interface"&gt;GDI&lt;/a&gt;, the rendering system introduced with Microsoft Windows 1.0. That sounds damning, but really most GUIs operated this way.&lt;/p&gt;

&lt;p&gt;Until the iPhone came along…&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.macresearch.org/tutorial-intro-core-animation" style="display:block;text-align:center"&gt;
    &lt;img src="http://cl.ly/3H143M1i2X2B1R2V1P2W/003.png"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you&amp;#8217;re using an iPhone, you&amp;#8217;re playing a hardware-accelerated 3D game. You know, the kind of 3D where everything is made out of hundreds of little triangles.&lt;/p&gt;

&lt;p&gt;When you flick through your list of friends in the Contacts app, you&amp;#8217;re causing those triangles to move around. And there&amp;#8217;s a &amp;#8220;camera,&amp;#8221; just like a 3D shooter, but the camera is fixed above the Contacts app&amp;#8217;s virtual surface and so it appears 2D.&lt;/p&gt;

&lt;p&gt;Which is a long way of saying that &lt;em&gt;everything&lt;/em&gt; on iOS is drawn using OpenGL. This is why animation on iOS is so hopelessly fast. You may have noticed that &lt;code&gt;-drawRect&lt;/code&gt; is not called for each frame of an animation. It&amp;#8217;s called once, then you draw your lines and circles and text onto an OpenGL surface (which you didn&amp;#8217;t even realize), then Core Animation moves these surfaces around like pulling on the strings of a marionette. All the final compositing for each frame is done in hardware by the GPU.&lt;/p&gt;

&lt;p&gt;Android seems to have made the decision early on that they wouldn&amp;#8217;t force their manufacturing partners to include a GPU. This decision made total sense back in the pre-iPhone days, but now it&amp;#8217;s causing pain, as even the new &lt;a href="http://android-developers.blogspot.com/2011/03/android-30-hardware-acceleration.html"&gt;hardware acceleration&lt;/a&gt; in Android 3.0 is limited by the original software-based compositing system.&lt;/p&gt;

&lt;p&gt;So here&amp;#8217;s the catch with the wonderful flexible layout system in Android: You must be very careful. If you animate certain kinds of properties, you can easily force the CPU to do all that fancy, expensive layout on each animation frame. And the CPU is very busy right now parsing some JSON from a web API or something, OK?&lt;/p&gt;

&lt;h2&gt;&lt;a style="color:black" href="#meridian" name="meridian"&gt;Meridian For Android&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;All in all, it took us about 4 months of development time to build and release &lt;a href="https://market.android.com/details?id=meridian.app"&gt;Meridian for Android&lt;/a&gt;.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img class="framed" src="http://cl.ly/3X1K3M39172m051A3q0Q/Screen_Shot_2011-07-31_at_8.52.46_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;When we first released &lt;a href="http://www.meridianapps.com"&gt;Meridian&lt;/a&gt;, our number one piece of feedback was &amp;#8220;Will you make an Android version please?&amp;#8221; Except often without the &amp;#8220;please.&amp;#8221;&lt;/p&gt;

&lt;p&gt;And it turns out Android is the &lt;em&gt;third&lt;/em&gt; platform for Meridian. The first was Windows Mobile, if you can believe that.&lt;/p&gt;

&lt;p style="text-align:center; margin-bottom: 0px"&gt;
    &lt;img src="http://cl.ly/1t0J2B0Z0i1s042G3844/hp_ipaq_210_enterprise-740678.png"/&gt;&lt;/p&gt;

&lt;p&gt;We started building what we now call &amp;#8220;Meridian,&amp;#8221; back before the iPhone existed. At the time, Windows Mobile was the only mobile platform capable of delivering the experience we wanted.&lt;/p&gt;

&lt;p&gt;So you could say I&amp;#8217;ve got a rather long view of things now. There will always be new platforms and new paradigms to learn. The best we can do is to understand where each one came from, and to embrace the positives and overcome the negatives as quickly as possible so we can ship some awesome features before everything changes again.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
    hr { 
        width: 75%;
        border: none;
        border-bottom: 1px solid #ccc;
        margin: 20px auto;
    }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/8239634061</link><guid>http://nfarina.com/post/8239634061</guid><pubDate>Mon, 01 Aug 2011 07:42:00 -0700</pubDate></item><item><title>A lightweight HTTP request class for iOS [2/2]</title><description>&lt;p&gt;&lt;a href="http://nfarina.com/post/3776625971/webrequest"&gt;Part 1&lt;/a&gt; | &lt;strong&gt;Part 2&lt;/strong&gt;&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;a href="https://github.com/nfarina/webrequest"&gt;
&lt;img src="http://cl.ly/1m1u2n1U2P2p0L0n2m0Q/hn.png" class="framed"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/nfarina/webrequest"&gt;Check out SMWebRequest on Github&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;a href="http://nfarina.com/post/3776625971/webrequest"&gt;Part 1&lt;/a&gt;, we introduced &lt;code&gt;SMWebRequest&lt;/code&gt; for making HTTP requests with little code. For instance, here&amp;#8217;s how your view controller could download an RSS feed and parse it with &lt;a href="http://github.com/nfarina/xmldocument"&gt;SMXMLDocument&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3P232f131C2r0g3J3F3j/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Looks simple, but there&amp;#8217;s a catch. See how we&amp;#8217;re taking our &lt;code&gt;NSData&lt;/code&gt; response from the server and turning it into XML? Well that&amp;#8217;s happening on the main thread, and guess what, parsing XML or JSON or whatever takes time. Maybe it takes a few milliseconds, or maybe it takes &lt;em&gt;10 whole seconds&lt;/em&gt; like when we parsed a gnarly RSS feed on the original iPhone.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;And your poor user, well she&amp;#8217;s probably scrolling through a table view or web view or something and just having a great time and then &lt;em&gt;screech&lt;/em&gt; everything grinds to a halt while you parse your giant 8MB SOAP response.&lt;/p&gt;

&lt;p&gt;The proper thing to do here is parse your data on a background thread. Which is relatively simple to do in Cocoa:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0Z2w3U2X1h3L1Y2x0Q2w/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;OK, so not terrible, but we&amp;#8217;re starting to have a lot of code and callbacks in our controller, and now we have to start worrying: What if the user leaves this page while we&amp;#8217;re in the middle of doing this work? We can easily cancel the &lt;code&gt;SMWebRequest&lt;/code&gt; in &lt;code&gt;-dealloc&lt;/code&gt; since it doesn&amp;#8217;t retain us as a target. But we &lt;a href="http://stackoverflow.com/questions/1351976/how-to-kill-a-thread-with-objective-c/1352023#1352023"&gt;can&amp;#8217;t kill the background thread&lt;/a&gt; if it&amp;#8217;s running and the system will &lt;code&gt;-retain&lt;/code&gt; us anyway so we have to wait until it completes and then detect somehow that we&amp;#8217;re no longer wanted so we don&amp;#8217;t kick off new operations. And what if the user presses &amp;#8220;Refresh&amp;#8221; or picks a different RSS feed or something while we&amp;#8217;re working in the background? Now we have to detach new background threads and detect old ones finishing and it gets really hairy.&lt;/p&gt;

&lt;!--link href='http://fonts.googleapis.com/css?family=Josefin+Sans' rel='stylesheet' type='text/css'--&gt;

&lt;div style="padding: 0 2.2em; font-size: 19px; color: #777; font-family: 'Josefin Sans', Helvetica Neue, arial, serif; "&gt;
&lt;p&gt;“Who wants a stylus?! You have to get &amp;#8216;em, and put &amp;#8216;em away, and you lose &amp;#8216;em. Yeeech. Nobody wants a stylus.”&lt;/p&gt;
&lt;span style="display: block; font-size: 16px; text-align:right; position:relative; left:0; top: -1em;"&gt;—&lt;a href="http://www.youtube.com/watch?v=sNhpBlINkUo"&gt;Steve Jobs&lt;/a&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;So let&amp;#8217;s not use a stylus. Basically, we don&amp;#8217;t want our controller class to have to worry about any of this stuff. The process should be abstracted away as &amp;#8220;Ask for RSS feed, receive RSS items later.&amp;#8221;&lt;/p&gt;

&lt;p&gt;And that&amp;#8217;s exactly what &lt;code&gt;SMWebRequest&lt;/code&gt; is designed for. In addition to the target/action callbacks, &lt;code&gt;SMWebRequest&lt;/code&gt; supports the &lt;code&gt;delegate&lt;/code&gt; pattern for processing data separately:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2a1Z1u0Z110D3c3k3Z0x/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;There are a couple great things happening here. First, we implement the delegate&amp;#8217;s &lt;code&gt;-webRequest:resultObjectForData:context:&lt;/code&gt; which is a totally isolated method. Its only job is to turn &lt;code&gt;NSData&lt;/code&gt; into objects. In this example, it&amp;#8217;s a &lt;code&gt;Class&lt;/code&gt; method which is great for background threads because it can&amp;#8217;t accidentally touch our instance variables even if it &lt;em&gt;wanted&lt;/em&gt; to.&lt;/p&gt;

&lt;p&gt;Second, the controller&amp;#8217;s &amp;#8220;complete&amp;#8221; method automatically receives the &lt;code&gt;NSArray&lt;/code&gt; we care about, rather than the whole &lt;code&gt;NSData&lt;/code&gt;. Ask for RSS feed, receive RSS items. And the whole operation is automatically cancelable just like any &lt;code&gt;SMWebRequest&lt;/code&gt; because it manages the threading for you.&lt;/p&gt;

&lt;p&gt;We can make our controller even cleaner by moving the parsing out into a &lt;a href="http://github.com/nfarina/modelobject"&gt;model class&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1p3M0i2h1v1B3e1i2Y1h/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;And this is how we write all our apps.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/nfarina/webrequest"&gt;github project&lt;/a&gt; demonstrates all this nicely by building basically an entire Hacker News RSS reader using very little code, whipped up by &lt;a href="http://bvanderveen.com/"&gt;Benjamin van der Veen&lt;/a&gt;, the original author of &lt;code&gt;SMWebRequest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I actually installed it on my iPhone and use it now to waste even more time than I already waste reading stuff on the internet.&lt;/p&gt;</description><link>http://nfarina.com/post/4112490145</link><guid>http://nfarina.com/post/4112490145</guid><pubDate>Mon, 28 Mar 2011 20:43:00 -0700</pubDate></item><item><title>A lightweight HTTP request class for iOS [1/2]</title><description>&lt;p&gt;&lt;strong&gt;Part 1&lt;/strong&gt; | &lt;a href="http://nfarina.com/post/4112490145/webrequest-2"&gt;Part 2&lt;/a&gt;&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;a href="https://github.com/nfarina/webrequest"&gt;
&lt;img src="http://cl.ly/2C2Y1C3s0x360z2W0f2j/winning.png" class="framed"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/nfarina/webrequest"&gt;Check out SMWebRequest on Github&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s say you&amp;#8217;re writing an app, either on iOS or the desktop, and you want to download some JSON data from a web service.&lt;/p&gt;

&lt;p&gt;With JavaScript and jQuery, this is a one-liner:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2r351x1n3K1K2K3I3M0u/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Sigh, if only.&lt;/p&gt;

&lt;p&gt;Well, technically you &lt;em&gt;could&lt;/em&gt; do this in one line:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/271z2x0R3S0P1I1e3V3V/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;But if you do that, you&amp;#8217;ll block the main thread until it completes, after which I will come over to your house and &lt;a href="http://twitter.com/nfarina/status/15915650664898560"&gt;stab you in the face&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To perform &lt;em&gt;asynchronous, cancellable&lt;/em&gt; HTTP requests in Cocoa, we have &lt;code&gt;NSURLConnection&lt;/code&gt;. Now, this is a pretty nice class. It gives you a great degree of control over the lifetime of the request and for managing the incoming response data. It also handles caching and system proxy settings and global request pooling and other useful things. So we want to use it.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Unfortunately, using it properly is a bit &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html"&gt;tedious&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1Y420U2p2T2q1Y2z272p/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;So that&amp;#8217;s all fine if we&amp;#8217;re only downloading like, &lt;em&gt;one thing&lt;/em&gt; in our app. And, maybe for Apple, downloading something from the Internet is a Big Deal.&lt;/p&gt;

&lt;p&gt;But if you&amp;#8217;re anything like us, your app is pretty much &lt;em&gt;constantly&lt;/em&gt; talking to servers. Authenticating, downloading, syncing, sharing, logging, refreshing&amp;#8230;there&amp;#8217;s easily dozens of places in each of our apps where we need to speak to some web server.&lt;/p&gt;

&lt;p&gt;So after a while, we thought &amp;#8220;maybe this can suck less!&amp;#8221; and wrote a utility class called &lt;code&gt;SMLoadedResource&lt;/code&gt; that used &lt;code&gt;NSURLConnection&lt;/code&gt; behind the scenes to easily download and process data. Then we threw it away and &lt;a href="http://bvanderveen.com/"&gt;Benjamin van der Veen&lt;/a&gt; wrote it &lt;em&gt;for real&lt;/em&gt; and called it &lt;code&gt;SMWebRequest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1g0y2M42243C3V3m3j1R/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SMWebRequest&lt;/code&gt; implements the &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html"&gt;target/action mechanism&lt;/a&gt; for its callbacks, just like &lt;code&gt;UIControl&lt;/code&gt;. That means you can write callback methods with sensible names like &lt;code&gt;trendsComplete&lt;/code&gt;, instead of handling everything in a generic &lt;code&gt;webRequest:didComplete:&lt;/code&gt; method with a ton of &lt;code&gt;if&lt;/code&gt; statements.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SMWebRequest&lt;/code&gt; also provides incredibly nice support for parsing your response data in a background thread while maintaining a separation of concerns. For more, continue to &lt;a href="http://nfarina.com/post/4112490145/webrequest-2"&gt;Part 2&lt;/a&gt;.&lt;/p&gt;</description><link>http://nfarina.com/post/3776625971</link><guid>http://nfarina.com/post/3776625971</guid><pubDate>Sat, 26 Mar 2011 19:57:00 -0700</pubDate></item><item><title>A lightweight XML parser for iOS</title><description>&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/nfarina/xmldocument"&gt;Check out SMXMLDocument on Github&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve ever tried to parse XML on the iPhone or iPad using &lt;code&gt;NSXMLParser&lt;/code&gt;, you may have wondered if you&amp;#8217;re &lt;em&gt;taking crazy pills&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://codesofa.com/blog/archive/2008/07/23/make-nsxmlparser-your-friend.html"&gt;
&lt;img src="http://cl.ly/1i3F2y3U3K1D2p082b2J/crap.png"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is this really how people parse XML on iOS? &lt;em&gt;Really&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;I mean, yes, it&amp;#8217;s true that using &lt;code&gt;NSXMLParser&lt;/code&gt; forces you to write extremely efficient stream-based parsing without buffering the entire XML structure in memory.&lt;/p&gt;

&lt;p&gt;But it also forces you, the savvy developer who already hates XML, to hate it even more as you write tons of conditional code and temporary classes so you can manually keep track of state.&lt;/p&gt;

&lt;p&gt;When we wrote our first iOS app, &lt;a href="http://www.spotlightmobile.com/apps"&gt;Style.com&lt;/a&gt;, we looked around for XML-parsing alternatives on iOS, and there are &lt;a href="http://foobarpig.com/iphone/touchxml-installation-guide.html"&gt;quite&lt;/a&gt; &lt;a href="http://www.TBXML.co.uk/TBXML/TBXML_Free.html"&gt;a&lt;/a&gt; &lt;a href="http://www.xmlsoft.org/"&gt;few&lt;/a&gt;. But they all felt like&amp;#8230;&lt;em&gt;too much&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What we really wanted was just the simplest possible class that would use &lt;code&gt;NSXMLParser&lt;/code&gt; itself to build up an easily-traversable Cocoa object hierarchy.&lt;/p&gt;

&lt;p&gt;So we &lt;a href="https://github.com/nfarina/xmldocument"&gt;made one&lt;/a&gt;. It&amp;#8217;s a single class, with like one page of code.&lt;/p&gt;

&lt;p&gt;And we find it very pleasant to use:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0t45212v340O3v1O1Q0i/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve used this class to parse XML on iOS for years now, and we&amp;#8217;ve never had any problems. You may want to fallback to &lt;code&gt;NSXMLParser&lt;/code&gt; if you have to deal with a multi-megabyte XML document though.&lt;/p&gt;</description><link>http://nfarina.com/post/2843708636</link><guid>http://nfarina.com/post/2843708636</guid><pubDate>Thu, 20 Jan 2011 09:28:00 -0800</pubDate></item><item><title>Simplify your models with SMModelObject</title><description>&lt;p&gt;&lt;a href="http://github.com/nfarina/modelobject"&gt;
    &lt;img src="http://cl.ly/2y3w3s063k0I082T471b/screenshot.png" style="width:500px; margin-bottom: -30px;"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="http://github.com/nfarina/modelobject"&gt;Check out SMModelObject on Github&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For almost every app we&amp;#8217;ve made, I find myself writing &amp;#8220;model classes&amp;#8221; to store structured data and logic. For instance, when you search for a book in the &lt;a href="http://www.barnesandnoble.com/iphone/index.asp"&gt;Barnes &amp;amp; Noble app&lt;/a&gt;, we fetch book results from an XML-based API and parse the XML into Cocoa objects that get passed around to our Controllers and Views.&lt;/p&gt;

&lt;p&gt;Pretty standard stuff. Now, one way to represent this data in memory would be to use anonymous NSArray+NSDictionary structures, like so:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1l0S0C2d2Z2i2C243G2x/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t know about you, but I cringe when I look at that code. So verbose, hard to read, no refactoring, no code completion; but most importantly, no type safety. I might write &lt;code&gt;@"pric"&lt;/code&gt; by mistake somewhere else and waste an hour debugging.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;So let&amp;#8217;s write a &amp;#8220;model class&amp;#8221; to store Books in a typesafe way.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2o2B010g2K02373R0k35/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Again, very standard. Now we can create these typesafe objects and access their properties directly:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2J0T2e0K0m130w0n0I1Z/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;So, ahhh, much better.&lt;/p&gt;

&lt;p&gt;But, man, that Book class seems like a lot of wasteful typing. Every property has to be written up to four times: declare instance var, write property, write &lt;code&gt;@synthesize&lt;/code&gt;, and release in &lt;code&gt;-dealloc&lt;/code&gt; if necessary.&lt;/p&gt;

&lt;p&gt;Seems manageable until you start dealing with real-life objects. In the Barnes &amp;amp; Noble app, Books have twenty-one properties. And Book is just one of a couple dozen model classes in the app. Sigh.&lt;/p&gt;

&lt;p&gt;Now, it turns out that ObjC has gotten better over the years, and as of the latest iOS SDK (4.2), LLVM+Clang can create your instance variables automatically.&lt;!--and now write your `@synthesize` for you as well--&gt; This is really nice!&lt;/p&gt;

&lt;p&gt;Leveraging this feature, &lt;!--(available now with a [simple Xcode preference][newobjc])--&gt; our Book class now looks like:&lt;/p&gt;

&lt;p&gt;&lt;!--img src="http://cl.ly/2W0S1Z1B1A37351f0J1Z/screenshot.png"/--&gt;
&lt;img src="http://cl.ly/2g3R41142r3b3q1i1c1k/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Which is great, but we can do even better. Objective-C makes it easy to introspect classes at runtime, so we&amp;#8217;ve created a simple base class called &lt;a href="http://github.com/nfarina/modelobject"&gt;SMModelObject&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using runtime introspection, &lt;code&gt;SMModelObject&lt;/code&gt; can do lots of great stuff for free:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Automatic release of properties in &lt;code&gt;-dealloc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Automatic implementation of &lt;code&gt;NSCopying&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Automatic implementation of &lt;code&gt;NSCoding&lt;/code&gt; so you can archive/unarchive your model objects to disk for state saving or for the clipboard&lt;/li&gt;
&lt;li&gt;Automatic &lt;code&gt;-isEqual&lt;/code&gt; and &lt;code&gt;-hash&lt;/code&gt; implementation to compare model objects by value&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Now our Book class looks like this:&lt;/p&gt;

&lt;p&gt;&lt;!--img src="http://cl.ly/2s212I1l1K0f1l2V0t0j/screenshot.png"/--&gt;
&lt;img src="http://cl.ly/052P3Y3u0k3n332Z2G0w/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SMModelObject&lt;/code&gt; even overrides &lt;code&gt;-description&lt;/code&gt; to print nicely-indented model object hierarchies for easy debugging.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/431s1M2C052N0e1F0j02/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Kickass.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;EDIT&lt;/strong&gt; 3/26/2011: This article used to demonstrate a feature of the Clang compiler that was experimental at the time: automatically writing @synthesize statements for you. It was awesome, but Apple decided it wasn&amp;#8217;t finished and so the official Xcode release doesn&amp;#8217;t contain it. I&amp;#8217;ll update this article again once it&amp;#8217;s released.&lt;/em&gt;&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;This all started when &lt;a href="http://twitter.com/AndrePang"&gt;André Pang&lt;/a&gt; wrote an amazing model base class called &lt;a href="https://github.com/andrep/RMModelObject"&gt;RMModelObject&lt;/a&gt; a few years back that is incredibly sophisticated and provides these same great features on the legacy ObjC runtime. &lt;code&gt;RMModelObject&lt;/code&gt; was the inspiration for my class, which was much easier to write since ObjC 2.0 does all the heavy lifting.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve historically used &lt;a href="https://github.com/andrep/RMModelObject"&gt;RMModelObject&lt;/a&gt; for all our model classes, so I must give full credit to André for this wonderful concept, and for saving me many extra hours of typing over the years.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
.hr, hr {
  border: 0;
  width: 512px;
  height: 1px;
  background: #ccc;
  margin: 25px auto;
  text-align: center;
}
.hr hr { display: none&amp;#160;!important; }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/2061838727</link><guid>http://nfarina.com/post/2061838727</guid><pubDate>Wed, 01 Dec 2010 11:16:00 -0800</pubDate></item><item><title>Raaarr: A Growl Style</title><description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Update:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;This style is now included with &lt;a href="http://growl.info/downloads"&gt;Growl 1.3&lt;/a&gt;! Go &lt;a href="http://itunes.apple.com/us/app/growl/id467939042?mt=12&amp;amp;ign-mpt=uo%3D4"&gt;download it from the App Store&lt;/a&gt; and enjoy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://enthusiastik.com/raaarr/"&gt;
    &lt;img src="http://dribbble.com/system/users/536/screenshots/75085/shot_1288921485.png?1288921499" class="frame big-frame"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="http://enthusiastik.com/raaarr/"&gt;Download Raaarr Now&lt;/a&gt;&lt;/em&gt; &lt;span style="font-size:90%"&gt;[Growl pre-1.3]&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;It all started way back 2 days ago when &lt;a href="http://www.enthusiastik.com/"&gt;James McDonald&lt;/a&gt; tweeted out a design for a new &lt;a href="http://growl.info/"&gt;Growl&lt;/a&gt; style:&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/2k1F2B3z2f1m1O3O0Y0J/screenshot.png" style="margin-bottom:10px"/&gt;&lt;img src="http://cl.ly/282Q2b1v3n1W3T332Z0T/screenshot.png" class="frame"/&gt;&lt;/center&gt;

&lt;p&gt;It was a lovely Photoshop design and I offered to take a stab at coding it up.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;I started with a basic HTML and CSS structure cribbed from the very slick &amp;#8220;Eleven&amp;#8221; Growl style by &lt;a href="http://fixedgear.ca"&gt;Christopher Lobay&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since Growl notifications are presented using Webkit, I was able to heavily leverage some advanced CSS3 techniques. For instance, the soft, semi-transparent gradient background and border effects are all done using CSS gradients.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/012D2Z3r0l24352S3m00/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;I soon had the basic design finished using only HTML+CSS.&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/2H1x1z0q3D3P0p3y3d00/screenshot.png" class="frame"/&gt;&lt;/center&gt;

&lt;p&gt;But I wasn&amp;#8217;t happy with the way most icons blended into the background of the notification. Like that yellow duck above.&lt;/p&gt;

&lt;p&gt;What I wanted was a dynamic subtle stroke around the outside of the icon. But a standard CSS &amp;#8220;border&amp;#8221; wouldn&amp;#8217;t work because the icon is technically square.&lt;/p&gt;

&lt;p&gt;So I turned to image-based &lt;a href="http://webkit.org/blog/181/css-masks/"&gt;CSS masking&lt;/a&gt;. I created a simple &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; that was a semi-opaque black square that sits behind the icon. Then, I used a reference to the icon image as the argument to a mask:&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/3k3N3m0c2W1l2y1M0H06/screenshot.png" style="margin-bottom: 7px"/&gt;&lt;img src="http://cl.ly/3C3d2K3Q0Q0X3w0E2z1F/screenshot.png" class="frame"/&gt;&lt;/center&gt;

&lt;p&gt;Then I stretched the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; to be slightly larger than the icon sitting on top of it, and voilà:&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/1o3m1I0n2p2P3t0r403j/screenshot.png" class="frame"/&gt;&lt;/center&gt;

&lt;p&gt;Finally, I wanted a nice subtle animation to give these notifications some personality. The animation should be fun, but also shouldn&amp;#8217;t break the physicality of the notification itself; I dislike things shifting about and animating for no reason.&lt;/p&gt;

&lt;p&gt;I ended up being inspired by iOS alert bubbles, and created a more subtle version of a &amp;#8220;pop-up&amp;#8221; using CSS3 hardware-accelerated animations:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/461w0f0p1Y2R182M1Y29/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;The result was extremely pleasing. You can see it on the &lt;a href="http://enthusiastik.com/raaarr/"&gt;demo site&lt;/a&gt; (best+accurate results in Safari).&lt;/p&gt;

&lt;p&gt;Speaking of the demo site, it&amp;#8217;s got a neat trick too: it demonstrates the style by embedding the style itself in the browser, which is pretty cool. But for the actual content of the demo notifications, it&amp;#8217;s dynamically querying &lt;a href="http://backtweets.com/"&gt;Backtweets&lt;/a&gt; for tweets that link to the site itself!&lt;/p&gt;

&lt;p&gt;So go &lt;a href="http://twitter.com/home?status=A%20simple,%20sexy%20Growl%20style%20for%20your%20Mac.%20http://www.enthusiastik.com/raaarr"&gt;tweet about the Raaarr style&lt;/a&gt; and you&amp;#8217;ll show up on the homepage.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
    .big-frame {
        border: 20px solid #f0f0f0;
    }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/1488599400</link><guid>http://nfarina.com/post/1488599400</guid><pubDate>Fri, 05 Nov 2010 09:22:00 -0700</pubDate></item><item><title>A Brief Review of the 11" MacBook Air</title><description>&lt;p&gt;&lt;img src="http://cl.ly/3U1K1q1o2U110o1S1n2Y/10-9-08-54-AM.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;OMG OMG OMG OMG OMG OMG OMG OMG OMG OMG&lt;/p&gt;

&lt;ul class="post-footer" style="margin-top: 10px; margin-bottom:50px"&gt;&lt;/ul&gt;&lt;h3&gt;A Less Brief Review of the 11&amp;#8221; MacBook Air&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s been my primary computer for a week or so, and I have zero regrets. I can&amp;#8217;t imagine going back to my 13&amp;#8221; MacBook Pro. Which, even with an SSD drive upgrade from Apple, felt slower than this machine.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t know how to explain it. I guess CPU clock speed is meaningless now? It seems most applications are IO-bound and so benefit &lt;em&gt;very much&lt;/em&gt; from the flash storage. Also the super-fast graphics.&lt;/p&gt;

&lt;p&gt;The screen is awesome and doesn&amp;#8217;t feel cramped at all. I even write code with Eclipse on this thing and it&amp;#8217;s great.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s something truly magical about this form factor. It&amp;#8217;s crazy ultra portable. Look, it even fits in my &lt;a href="http://www.google.com/search?q=cole+haan+newspaper+bag"&gt;man-bag&lt;/a&gt; with my iPad!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0B232I072F0K1G40102F/10-9-09-09-AM.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s basically no reason to buy any other computer, especially for the price. It&amp;#8217;s &lt;em&gt;that good&lt;/em&gt;.&lt;/p&gt;</description><link>http://nfarina.com/post/1480261883</link><guid>http://nfarina.com/post/1480261883</guid><pubDate>Thu, 04 Nov 2010 09:39:00 -0700</pubDate></item><item><title>DropDAV = Dropbox + WebDAV</title><description>&lt;p&gt;&lt;img src="http://cl.ly/3E0l3g2q0A403j0b1a20/screenshot-1.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://dropdav.appspot.com"&gt;Go use DropDAV now&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When the new iWork update for iPad dropped, I was in the Bay Area for an Important Meeting. While in transport to this meeting, I had created a Keynote presentation on my iPad. Because I want to be hip with the kids!&lt;/p&gt;

&lt;p&gt;Now we&amp;#8217;re sitting in the rental car in the parking lot of the Big Company, and the presentation starts in 5 minutes, and I need to shuttle the Keynote file off my iPad and onto my MacBook to throw in some crap I made in Photoshop about how awesome we are.&lt;/p&gt;

&lt;p&gt;I ended up dragging out my sync cable and moving the files through iTunes. It felt dirty and uncool. But it was OK, because we never even had a chance to show our Big Presentation and spent the whole meeting chatting instead.&lt;/p&gt;

&lt;p&gt;What would have been perfect is if Dropbox had a WebDAV API, since 1) Dropbox is civilization, and 2) The new iWork integrates with WebDAV and MobileMe. Then I could just post the file straight from iWork to my Dropbox and it would magically appear on my MacBook!&lt;/p&gt;

&lt;p&gt;So this weekend I set out to build a WebDAV frontend to Dropbox. And &lt;a href="https://dropdav.appspot.com"&gt;here it is&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wrote it on Google App Engine since I&amp;#8217;d already implemented a &lt;a href="http://github.com/nfarina/simpledav"&gt;WebDAV server for App Engine&lt;/a&gt;, and so that I don&amp;#8217;t have to think about hosting. The Dropbox API part was made much simpler thanks to their &lt;a href="http://bitbucket.org/dropboxapi/dropbox-client-python"&gt;official Python API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sadly, you can only transfer files up to 1MB, due to limitations with &lt;a href="http://code.google.com/appengine/docs/python/urlfetch/"&gt;urlfetch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Otherwise, feel free to use it to get things into and out of your Dropbox until they provide an &lt;a href="https://www.dropbox.com/votebox/122/webdav-support"&gt;official WebDAV frontend&lt;/a&gt;.&lt;/p&gt;</description><link>http://nfarina.com/post/1344626185</link><guid>http://nfarina.com/post/1344626185</guid><pubDate>Mon, 18 Oct 2010 09:42:00 -0700</pubDate></item><item><title>iPad Does Everything</title><description>&lt;p&gt;In 1984, Bang &amp;amp; Olufsen released the &lt;a href="http://www.beoworld.org/prod_details.asp?pid=957"&gt;Beosystem 5000&lt;/a&gt;, a large component-based stereo system. It shipped with the most awesome remote control of all time, the &lt;a href="http://beocentral.com/mastercontrolpanel5000"&gt;Master Control Panel 5000&lt;/a&gt;.&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/1e322i0K1M3a1M283U2u/Screen_shot_2010-09-29_at_9.15.29_AM.png" style="margin-bottom: -15px"/&gt;&lt;/center&gt;

&lt;p&gt;I was seven years old when I saw this thing at my Aunt&amp;#8217;s house and it was just about the coolest thing I&amp;#8217;d ever seen. That bottom silver panel flips open to reveal &lt;em&gt;even more buttons&lt;/em&gt;. It&amp;#8217;s totally sick.&lt;/p&gt;

&lt;p&gt;Fast forward many years later, and now I finally have one for myself. Except this time it&amp;#8217;s a &lt;a href="http://sonos.com/ipad"&gt;free app&lt;/a&gt; I downloaded from the App Store to control our &lt;a href="http://sonos.com"&gt;Sonos&lt;/a&gt; music system.&lt;/p&gt;

&lt;center&gt;
&lt;img src="http://cl.ly/3H122V2v222L3L1S340y/Sonos_iPad.jpg" class="framed"/&gt;&lt;/center&gt;

&lt;p&gt;I wonder what this will look like in another 25 years?&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
center {
    margin-bottom: 20px;
}
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/1210958689</link><guid>http://nfarina.com/post/1210958689</guid><pubDate>Wed, 29 Sep 2010 09:35:00 -0700</pubDate></item><item><title>iOS Icon Template for Perfectionists</title><description>&lt;p&gt;&lt;a href="http://db.tt/SBmj854" style="font-style:italic"&gt;
&lt;img src="http://cl.ly/100q203O3h3I021u2C3j/iOS_icon_template_by_nfarina.png" class="framed"/&gt;
Download the modified template
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating a few icons with the excellent &lt;a href="http://blog.cocoia.com/2010/iphone-4-icon-psd-file/"&gt;iPhone 4 icon PSD template from Cocoia&lt;/a&gt;, we started noticing the dreaded &amp;#8220;black corner pixels&amp;#8221; effect on iOS and iTunes, which you see all over the place these days.&lt;/p&gt;

&lt;div class="framed"&gt;
&lt;p style="text-align:center"&gt;
&lt;img src="http://cl.ly/0k1R1k1S3O003V2Z2Q0c/Untitled-1.png" style="border: 1px solid #999"/&gt;&lt;img src="http://cl.ly/3U14340d2y2V0U0q023C/Screen_shot_2010-09-25_at_8.49.18_AM.png" style="margin: 0 15px"/&gt;&lt;img src="http://cl.ly/362p1W2y1l203E063k0n/Screen_shot_2010-09-25_at_9.09.21_AM.png"/&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Why does this happen? It&amp;#8217;s because Apple is very liberal about the compositing of your image. &lt;!-- more --&gt; Let&amp;#8217;s say you make a nice icon in Photoshop, and &amp;#8220;eyeball&amp;#8221; the corners:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/272c240l352b233a3c0w/Screen_shot_2010-09-25_at_9.02.37_AM.png" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;When iOS gets ahold of your nice transparent icon, it will immediately slap it on a black background…&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1c0B262X1b2E3o0M1x25/Untitled-2.png"/&gt;&lt;/p&gt;

&lt;p&gt;…then apply this masking image:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3r0w163U0042061f0f3P/AppIconMask-72.png"/&gt;&lt;/p&gt;

&lt;p&gt;Now your icon looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3T1j190x3P1K3f0N2U18/Untitled-3.png"/&gt;&lt;/p&gt;

&lt;p&gt;You could sneak this by in the past because the iPhone homescreen was always black anyway. But now that we have customizable homescreen wallpapers, these black corners will be revealed right quick.&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;How did we fix this problem? Well first off, we started by rebuilding &lt;a href="http://blog.cocoia.com/2010/iphone-4-icon-psd-file/"&gt;Cocoia&amp;#8217;s template&lt;/a&gt; around the system masks we extracted from the iOS firmware.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
    &lt;img src="http://cl.ly/3t1E2w3f1j010B1a3v0q/Screen_shot_2010-09-25_at_9.24.47_AM.png" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;But even designing against the exact masks isn&amp;#8217;t enough to avoid a faint black line around the corners. So we also made it easy to &amp;#8220;extend&amp;#8221; the outer pixels of your icon all the way to the edges using a Smart Object.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;img src="http://cl.ly/3V2F2O1C270P0U3t441i/Untitled-4.png"/&gt;&lt;span class="equation"&gt;+&lt;/span&gt;
&lt;img src="http://cl.ly/0x402x0z2Q42112v3G42/Untitled-4-1.png"/&gt;&lt;span class="equation"&gt;=&lt;/span&gt;
&lt;img src="http://cl.ly/262i1z2p2t3W1C420x2e/Untitled-4-2.png"/&gt;&lt;/p&gt;

&lt;p&gt;Look carefully at the colors we&amp;#8217;ve chosen to extend, it&amp;#8217;s not the dark red interior background, it&amp;#8217;s the &lt;em&gt;outer pixel&lt;/em&gt;:&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;img src="http://cl.ly/3q252U3T0m3b3l3l0y1S/Screen_shot_2010-09-25_at_10.10.39_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;So now Apple can apply all the masks and effects they want and your icon will still look perfect:&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;img src="http://cl.ly/0A3g0w153f172T2k2N0b/Screen_shot_2010-09-25_at_9.43.38_AM.png" class="framed"/&gt;&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;The template leverages Photoshop Smart Objects heavily to  ease the burden of designing all your different icon sizes simultaneously.&lt;/p&gt;

&lt;p style="text-align:center"&gt;
&lt;img src="http://cl.ly/2t3j3b3C0z3H1X2u3445/Screen_shot_2010-09-25_at_10.05.45_AM.png" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;But here&amp;#8217;s the best part: when you&amp;#8217;re ready to export the final output, just unhide the top &lt;code&gt;Corner Mask&lt;/code&gt; preview layer and Save for Web:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3Z0R3Y010c3T022W0N0z/Screen_shot_2010-09-25_at_8.31.53_AM.png"/&gt;&lt;/p&gt;

&lt;p&gt;Each icon has its own Slice, set to export with the correct filenames like &amp;#8220;Icon.png,&amp;#8221; &amp;#8220;Icon@2x.png,&amp;#8221; and even &amp;#8220;iTunesArtwork&amp;#8221; for .ipa distribution.&lt;/p&gt;

&lt;p&gt;Just one save and you&amp;#8217;re done.&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;Comments? Feedback? Hit me up on &lt;a href="http://twitter.com/nfarina"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
div.framed {
    border: 1px solid #999;
    margin: 30px 0;
}
span.equation {
    font-size: 31px;
    margin: 8px;
    position: relative;
    top: -25px
}
center {
    margin-bottom: 20px;
}
.hr, hr {
  border: 0;
  width: 512px;
  height: 1px;
  background: #ccc;
  margin: 25px auto;
  text-align: center;
}
.hr hr { display: none&amp;#160;!important; }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/1185879730</link><guid>http://nfarina.com/post/1185879730</guid><pubDate>Sat, 25 Sep 2010 20:16:00 -0700</pubDate></item><item><title>Moving my Photos to the Cloud</title><description>&lt;p&gt;I went to visit my extended family on Lake Michigan last weekend, and ended up snapping a few fancy-schmancy HDR photos on my iPhone 4.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1T2T1k0y0D3S0U261K13/Beach.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;Like the world needs more photos of beaches.&lt;/p&gt;

&lt;p&gt;Later, I captured some germane pictures featuring actual family members. After which I thought, man I sure would like to show these to my grandparents on my big-screened iPad which is &lt;em&gt;sitting right here&lt;/em&gt;. Also, I&amp;#8217;m on the phone with my Mom, and can&amp;#8217;t I send them to her, too?&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;So yes, because I&amp;#8217;m a nerd I can make these things happen but &lt;em&gt;ugh&lt;/em&gt;, I&amp;#8217;ve gotta 1) unpack my laptop and dig out my cables and 2) sync my iPhone which takes forever, then I&amp;#8217;ve gotta 3) deal with all the other crap in my Camera Roll and organize everything into iPhoto Events and such, then post them to a &amp;#8220;place&amp;#8221; like Flickr or MobileMe or god forbid Facebook, then 4) Re-sync my iPhone and iPad to get the newly organized photos back on there. By which time everyone&amp;#8217;s moved onto watching Fox News and chastising me for buying a Prius.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0S0K3e223v2t291t0810/Prius.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;Dealing with photos shouldn&amp;#8217;t be this cumbersome. Enter &lt;a href="http://picasaweb.google.com"&gt;Google Picasa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I looked at a few cloud-based photo storage systems, and chose Picasa for a few reasons. First, it&amp;#8217;s powered by The Google, so I&amp;#8217;m not concerned about their infrastructure or ongoing development. Second, it&amp;#8217;s been around for a while so they have a great ecosystem of tools.&lt;/p&gt;

&lt;p&gt;Most importantly, they have &lt;a href="http://www.webalbumsapp.com"&gt;Web Albums&lt;/a&gt;: a 3rd party app for iPhone and iPad that, seriously here, rivals Apple&amp;#8217;s built-in Photos app.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2U280o0i2Y2g3p3F3b02/WebAlbums.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;Web Albums has replaced the native Photos app on my iOS devices. Now I can take photos using the Camera app, then go to Web Albums and make a new album, queue it for upload to Picasaweb, and copy the private viewing URL to the clipboard so I can email the link to Mom right from my phone. Meanwhile I grab the iPad and &amp;#8220;pull to refresh&amp;#8221; the album list, and &lt;em&gt;BAM&lt;/em&gt; it&amp;#8217;s right there.&lt;/p&gt;

&lt;p&gt;So that&amp;#8217;s my new workflow, and all my photos will be stored on Google&amp;#8217;s servers rather than carting them around on my laptop and worrying about backup.&lt;/p&gt;

&lt;p&gt;Picasa also makes it dead easy to migrate my existing photos from iPhoto using their &amp;#8220;native&amp;#8221; &lt;a href="http://picasa.google.com/mac/"&gt;OS X application&lt;/a&gt;. Fortunately I only need to use it for this single purpose, otherwise I&amp;#8217;d die having to look at the &lt;em&gt;jankiest UI widgets on the Macintosh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1l1b2m113Z0d0S2N1m1z/PicasaUI.jpg" class="framed"/&gt;&lt;/p&gt;

&lt;p&gt;(Aside from the UI, this program is otherwise quite powerful and impressive. It also did a better job identifying faces than iPhoto.)&lt;/p&gt;

&lt;p&gt;The best part is that Picasa&amp;#8217;s hosting is really cheap. It&amp;#8217;ll only cost me $5 a year to store my 17GB collection of all the digital pictures and video I&amp;#8217;ve ever captured.&lt;/p&gt;

&lt;p&gt;&lt;style&gt;
    img.framed {
        border: 1px solid #ddd;
        border-radius:6px;
        -webkit-box-shadow: 0&amp;#160;2px 3px rgba(0,0,0,0.3);
        -moz-box-shadow: 0&amp;#160;2px 3px rgba(0,0,0,0.3);
    }
&lt;/style&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/1115841704</link><guid>http://nfarina.com/post/1115841704</guid><pubDate>Mon, 13 Sep 2010 20:07:00 -0700</pubDate></item><item><title>iPhone 4: &lt;i&gt;No Italics!&lt;/i&gt;</title><description>&lt;p&gt;This sounds crazy, but seems to be true: &lt;code&gt;+[UIFont italicSystemFontOfSize:]&lt;/code&gt; simply returns a regular non-italic font on iPhone 4 hardware.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://developer.apple.com/iphone/library/releasenotes/General/RN-iPhoneSDK-4_0/index.html"&gt;release notes&lt;/a&gt; state:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;iPhone 4 uses a different system font than earlier devices. 
  References to the Helvetica font in nib files will be 
  decoded as the system font on these newer devices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &amp;#8220;different system font&amp;#8221; appears to be Helvetica Neue, for which there is no italic version included.&lt;/p&gt;

&lt;p&gt;Since you&amp;#8217;ll always want to use the system font for your user interface, what this means is: &lt;em&gt;no italics for your UI&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This absolutely must be intentional and not a bug. Changing the system font on a new iPhone model for which a primary new feature is better font rendering, is a &lt;em&gt;huge deal&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not complaining about it, I think it&amp;#8217;s a fine decision, but also extremely interesting, don&amp;#8217;t you think?&lt;/p&gt;</description><link>http://nfarina.com/post/738543430</link><guid>http://nfarina.com/post/738543430</guid><pubDate>Sat, 26 Jun 2010 08:12:11 -0700</pubDate></item><item><title>How to check out new music on Rdio</title><description>&lt;p&gt;1) First, search for an artist you&amp;#8217;re interested in:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3k440W3y0S3H2z3F473s/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Now scroll down to &amp;#8220;Popular Songs.&amp;#8221; See that Play button?&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0v1Q0T3R1D0S0i063B0t/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;2) That&amp;#8217;s the one. Press that. Press it.&lt;/p&gt;

&lt;p&gt;3) Now you&amp;#8217;re listening to some &lt;em&gt;awesome&lt;/em&gt; music. How easy was that?!&lt;/p&gt;

&lt;p&gt;For extra fun, share it with your friends:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1y463k0h032W29071X1M/screenshot.png" alt=""/&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/722107169</link><guid>http://nfarina.com/post/722107169</guid><pubDate>Mon, 21 Jun 2010 08:16:00 -0700</pubDate></item><item><title>Improvements to Google Wave Notifier</title><description>&lt;p&gt;&lt;em&gt;&lt;a href="https://nfarina.s3.amazonaws.com/google-wave-notifier/GoogleWaveNotifier.zip"&gt;Download the notifier now&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I tried out the &lt;a href="http://github.com/hiroshi/Unofficial-Google-Wave-Notifier"&gt;Unofficial Google Wave Notifier&lt;/a&gt; and liked its functionality, but wasn&amp;#8217;t thrilled with the UI:&lt;/p&gt;

&lt;div style="text-align:center; margin-bottom: 20px"&gt;
    &lt;img src="http://2.bp.blogspot.com/_qsyweV0vXTA/St57xQfwoeI/AAAAAAAAAJU/oCCiTBmIlqQ/s400/unofficial+google+wave+notifier.png"/&gt;&lt;/div&gt;

&lt;p&gt;So I made some changes:&lt;/p&gt;

&lt;div style="text-align:center; margin-bottom: 20px"&gt;
    &lt;img src="http://cl.ly/2m0f06431s2U0n0R1P2V/WaveNotifierOpen.png"/&gt;&lt;/div&gt;

&lt;p&gt;The icon glows blue when you have unread waves, inspired by &lt;a href="http://www.atebits.com/tweetie-mac/"&gt;Tweetie for Mac&lt;/a&gt;:&lt;/p&gt;

&lt;div style="text-align:center"&gt;
    &lt;img src="http://cl.ly/0m2U3c0o143F1Q1O3Y2G/WaveNotifier.png" style="margin-bottom:25px"/&gt;&lt;/div&gt;

&lt;p&gt;I also added a selector for choosing which browser the Notifier opens Google Wave in when you click things.&lt;/p&gt;

&lt;div style="text-align:center; margin-bottom: 20px"&gt;
    &lt;img src="http://cl.ly/3b433a3Q361N1M281y1K/WaveNotifierBrowsers.png"/&gt;&lt;/div&gt;

&lt;p&gt;Creating this selector in Cocoa on OS X was a lot more involved than I thought going in. But at least it&amp;#8217;s not Windows, which would have been 10 times more painful.&lt;/p&gt;

&lt;p&gt;I also refactored the notifier to be fully asynchronous so it doesn&amp;#8217;t block the main thread and is always responsive.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/nfarina/Google-Wave-Notifier"&gt;Check it out on Github.&lt;/a&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/475049089</link><guid>http://nfarina.com/post/475049089</guid><pubDate>Fri, 26 Mar 2010 20:01:00 -0700</pubDate></item><item><title>There, I fixed Xcode—You’re Welcome.</title><description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Update:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Xcode 4 ships with a brand new completion engine and UI that makes my hackjob plugin look like a toy. Go use that instead!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="http://code.google.com/p/xcode-auto-assistant/downloads/list"&gt;Download xcode-auto-assistant now&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href="http://nfarina.com/post/389462700/code-completion-and-xcode"&gt;last installment&lt;/a&gt;, I discussed Xcode&amp;#8217;s frustrating implementation of code completion.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve now &lt;a href="http://code.google.com/p/xcode-auto-assistant/"&gt;taken matters into my own hands&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/17430S093Y1X0m2c1m2Y/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;It turns out Xcode has an (undocumented) plugin system. And it also turns out that &lt;a href="http://ciaranwal.sh/"&gt;this guy&lt;/a&gt; created a &lt;a href="http://github.com/ciaran/xcode-bracket-matcher"&gt;really fantastic plugin&lt;/a&gt; for Xcode that automatically inserts a matching opening bracket &amp;#8216;&lt;code&gt;[&lt;/code&gt;&amp;#8217; when typing the closing bracket &amp;#8216;&lt;code&gt;]&lt;/code&gt;&amp;#8217;.&lt;/p&gt;

&lt;p&gt;Now, it turns out Apple added this bracket-insertion feature on their own, possibly being inspired by this, so the plugin is now just reference material.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Really useful&lt;/em&gt; reference material for doing what I want to do.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;I&amp;#8217;ll save the nitty-gritty details of how the plugin works for a later post (or just &lt;a href="http://code.google.com/p/xcode-auto-assistant/source/checkout"&gt;browse the source&lt;/a&gt;). Let&amp;#8217;s just say that we have access to keystrokes as you type them in Xcode. How would we use that to achieve automatic completion list display?&lt;/p&gt;

&lt;h2&gt;Take 1: Popup all the time!&lt;/h2&gt;

&lt;p&gt;The most useful behavior, it seems, is for the popup list to appear as soon as you type a reasonable character that can be completed, such as an alphabetical character. Here we&amp;#8217;ll type &amp;#8216;&lt;code&gt;u&lt;/code&gt;&amp;#8217; because we want &lt;code&gt;UIViewController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/16151H2V0T3q2r1O1212/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;So that&amp;#8217;s the first thing I implemented. Listen for alphabetical character, popup the list.&lt;/p&gt;

&lt;p&gt;The problem turns out to be that the list takes &amp;#8220;a while&amp;#8221; to appear, because we&amp;#8217;re in Objective-C which is still &lt;strong&gt;C&lt;/strong&gt; and the number of legal symbols you can type in a particular location is &lt;em&gt;immense&lt;/em&gt;. I mean look at that tiny scrollbar! There&amp;#8217;s all manner of detritus in there like &lt;code&gt;u_quad_t&lt;/code&gt; and &lt;code&gt;UIKIT_STATIC_INLINE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You might think, no problem, I&amp;#8217;ll just ignore the popup and keep typing because the list will narrow itself down as I go. But, in practice, it turns out to be extremely annoying because you can&amp;#8217;t type small words like &amp;#8220;&lt;code&gt;if&lt;/code&gt;&amp;#8221; and &amp;#8220;&lt;code&gt;for&lt;/code&gt;&amp;#8221; without the popup list slowing you down.&lt;/p&gt;

&lt;h2&gt;Examine our options&lt;/h2&gt;

&lt;p&gt;I imagine that Apple encountered this same problem, and it seems the way they addressed it was by analyzing the number of items that &lt;em&gt;would&lt;/em&gt; match and only giving you a suggested completion if the number of possible matches is small.&lt;/p&gt;

&lt;p&gt;This is why, with Apple&amp;#8217;s completion, you must type &amp;#8220;&lt;code&gt;nss&lt;/code&gt;&amp;#8221; before it will automatically suggest something like &amp;#8220;&lt;code&gt;NSString&lt;/code&gt;&amp;#8221;. If you just type &amp;#8220;&lt;code&gt;ns&lt;/code&gt;&amp;#8221; you can sit there forever and it&amp;#8217;ll never suggest anything. But if you type &amp;#8220;&lt;code&gt;cl&lt;/code&gt;&amp;#8221; it might suggest &amp;#8220;&lt;code&gt;CLLocation&lt;/code&gt;&amp;#8221; because there aren&amp;#8217;t a lot of other things starting with &amp;#8220;&lt;code&gt;cl&lt;/code&gt;&amp;#8221;.&lt;/p&gt;

&lt;p&gt;My beef with this approach is that it&amp;#8217;s &lt;a href="http://nfarina.com/post/389462700/code-completion-and-xcode"&gt;unpredictable&lt;/a&gt;. How do I know how many letters I&amp;#8217;m supposed to type before I can press &lt;code&gt;enter&lt;/code&gt; and move on?&lt;/p&gt;

&lt;h2&gt;Take 2: Smart delay&lt;/h2&gt;

&lt;p&gt;The solution turned out to be surprisingly simple. Display the list after typing any alphanumeric character, but with a delay &lt;em&gt;proportional to the number of characters in the word entered thus far&lt;/em&gt;. On the 4th character and beyond, the list always appears immediately.&lt;/p&gt;

&lt;p&gt;This way you can type &amp;#8220;&lt;code&gt;uivi[enter]&lt;/code&gt;&amp;#8221; &lt;em&gt;as fast as possible&lt;/em&gt; and you get &lt;code&gt;UIViewController&lt;/code&gt; (depending on your typing history, but this is intuitive).&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3C1Y1L3D2S131v2A1H2I/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;By the time you get to the 4th character, the list is almost always reasonably small and therefore much more helpful.&lt;/p&gt;

&lt;p&gt;If you just type &amp;#8220;&lt;code&gt;u&lt;/code&gt;&amp;#8221; and forget what you were doing, we&amp;#8217;ll wait about 0.4 seconds before presenting the list to help you.&lt;/p&gt;

&lt;p&gt;More importantly, you can type &amp;#8220;&lt;code&gt;for (int i = 0…&lt;/code&gt;&amp;#8221; at normal typing speed without the popup appearing at all, and once you get stuck on something you&amp;#8217;ll pause naturally and only then will the list appear.&lt;/p&gt;

&lt;h2&gt;Extras&lt;/h2&gt;

&lt;p&gt;Of course, you don&amp;#8217;t want the list appearing on just &lt;em&gt;any&lt;/em&gt; alphanumeric character: If you&amp;#8217;re writing a string or a comment, the list isn&amp;#8217;t going to help you. So the plugin does some extra work to detect those situations. It&amp;#8217;s not a full-on &lt;a href="http://en.wikipedia.org/wiki/Lexical_analysis"&gt;lexer&lt;/a&gt; but it seems to work 99% of the time.&lt;/p&gt;

&lt;p&gt;Additionally, if you type a period &amp;#8216;&lt;code&gt;.&lt;/code&gt;&amp;#8217; to access a struct member or ObjC property, the list always appears immediately.&lt;/p&gt;

&lt;p&gt;One last neat feature: When you type a semicolon, it will be automatically moved to the &lt;em&gt;end&lt;/em&gt; of the line as necessary. I don&amp;#8217;t know about you, but I often find myself in this kind of situation:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1K332y0z3L0U0k1p2R0O/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;…having just typed a method name and needing to cap off the line with a semicolon. Normally I&amp;#8217;d have to go find the right arrow key first, but with the plugin you just type &amp;#8216;&lt;code&gt;;&lt;/code&gt;&amp;#8217; and it puts it in the right place.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3v1t2w420t1L2X0f2q0T/screenshot.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Pretty cool!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.google.com/p/xcode-auto-assistant/"&gt;Try the plugin here.&lt;/a&gt;&lt;/p&gt;</description><link>http://nfarina.com/post/428544140</link><guid>http://nfarina.com/post/428544140</guid><pubDate>Fri, 05 Mar 2010 20:01:00 -0800</pubDate></item><item><title>Code Completion and XCode</title><description>&lt;p&gt;&lt;em&gt;Update: I &lt;a href="http://nfarina.com/post/428544140/there-i-fixed-xcode-youre-welcome"&gt;wrote a plugin&lt;/a&gt; to address these issues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Later Update:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Xcode 4 Preview 3 shipped with a brand new completion engine and UI that happens to address all these issues with aplomb. Yays!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The newish mac app &lt;a href="http://macrabbit.com/espresso/"&gt;Espresso&lt;/a&gt; contains a great (and uncommonly beautiful) implementation of code completion.&lt;/p&gt;

&lt;p&gt;It goes like this. Say you&amp;#8217;re editing a CSS file:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0i152a0k2T1u2w0f3b3S/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s a nice blue background, but you also want a border. You start by typing the letter &amp;#8220;&lt;code&gt;b&lt;/code&gt;&amp;#8221;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/140q3G133Q0I2U0q1z3b/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Since Espresso knows that there are many possible options that start with &amp;#8220;&lt;code&gt;b&lt;/code&gt;&amp;#8221;, it presents them to you in this lovely but minimal popup. You can use the arrows and press &lt;code&gt;enter&lt;/code&gt; to select something from the list. &lt;em&gt;Or&lt;/em&gt;, you can pretend the list never appeared and keep typing. Once you type enough to eliminate all other options, the list disappears and you&amp;#8217;re left with a more standard OS X &amp;#8220;completion&amp;#8221; highlight. You can still press &lt;code&gt;enter&lt;/code&gt; to accept this last suggestion.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/2K3j1s412x2x3T3N2z34/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;The two things I want to emphasize about this workflow are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;It&amp;#8217;s &lt;strong&gt;predictable&lt;/strong&gt;. I trust Espresso to always give me all possible relevant options after each keypress. And I know that I just press &lt;code&gt;enter&lt;/code&gt; to accept and move on.&lt;/li&gt;
&lt;li&gt;It&amp;#8217;s &lt;strong&gt;useful&lt;/strong&gt;. Whenever there are multiple options, they are presented to me in the list, and the list appears automatically when needed.&lt;/li&gt;
&lt;/ul&gt;&lt;!-- more --&gt;&lt;h3&gt;Predictable&lt;/h3&gt;

&lt;p&gt;XCode goes like this. Say you&amp;#8217;re writing some Objective-C:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1h2U35143K121m0T3P0x/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;We need to make a new instance of &lt;code&gt;UIViewController&lt;/code&gt;, so we begin our journey of typing the class name.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/12322z1X2y282j3a371n/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;XCode does nothing so far. We know it has a set of suggestions to help us—if you press &lt;code&gt;ESC&lt;/code&gt; now, you&amp;#8217;ll see a nice list of all the classes starting with &amp;#8220;&lt;code&gt;UI&lt;/code&gt;&amp;#8221;. But for some reason it&amp;#8217;s decided not to jump in yet. &lt;span style="font-size:75%"&gt;(Note: My Code Sense delay is set to &lt;code&gt;Immediate&lt;/code&gt;)&lt;/span&gt;. We press on, typing &amp;#8220;&lt;code&gt;v&lt;/code&gt;&amp;#8221;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/0G343P1z2e0O06272f0b/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Ah ha, there it is! Clever XCode! That&amp;#8217;s what we want—so we&amp;#8217;ll press &lt;code&gt;enter&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3K3K2m3W2g1f012p1J2f/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Curious&lt;/em&gt;. It has only &lt;em&gt;partially&lt;/em&gt; completed the word. See how before, only the &amp;#8216;&lt;code&gt;i&lt;/code&gt;&amp;#8217; was highlighted? This is a (newish?) feature of XCode. It turns out there are a few other classes starting with the prefix &amp;#8220;&lt;code&gt;UIVi&lt;/code&gt;&amp;#8221; and it doesn&amp;#8217;t want to assume that I want something starting with &lt;code&gt;UIView&lt;/code&gt; and not, say, &lt;code&gt;UIVideoEditorController&lt;/code&gt; which I never knew existed until just now.&lt;/p&gt;

&lt;p&gt;At this point if I press &lt;code&gt;enter&lt;/code&gt; again, it will go ahead and fill in the rest of the word.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/1o1V1Z3a2L3G3O3P2p1X/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;So it eventually gave me what I wanted. But here&amp;#8217;s a wrinkle: if I would have typed &amp;#8220;&lt;code&gt;uivi&lt;/code&gt;&amp;#8221; myself first, it would have suggested &lt;code&gt;UIViewController&lt;/code&gt; just the same, but in that case it would have completed the entire word when I pressed &lt;code&gt;enter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The problem here is that XCode is not &lt;strong&gt;predictable&lt;/strong&gt;. When I&amp;#8217;m typing code, my brain is moving faster than my fingers. I can &lt;em&gt;decide&lt;/em&gt; to type &lt;code&gt;[[[UIViewController alloc] init] autorelease]&lt;/code&gt; a &lt;em&gt;hell&lt;/em&gt; of a lot faster than I can actually write it. And my brain can&amp;#8217;t move on to a more interesting problem until it can give my fingers a known sequence of keys to press. XCode&amp;#8217;s completion is a different back-and-forth conversation with the editor every time. How do I get it to finish &lt;code&gt;UIViewContoller&lt;/code&gt;? Do I press &lt;code&gt;enter&lt;/code&gt; once, twice, three times? It depends how many characters I typed first, which &lt;em&gt;also&lt;/em&gt; depends on factors like XCode tailoring its suggestions based on my code history.&lt;/p&gt;

&lt;h3&gt;Useful&lt;/h3&gt;

&lt;p&gt;Here&amp;#8217;s another example. Let&amp;#8217;s set the &lt;code&gt;frame&lt;/code&gt; of our new controller&amp;#8217;s view, by first declaring a new &lt;code&gt;CGRect&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/02210P3s3k413B1q0r3C/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;Now here I&amp;#8217;ve typed the letters &lt;code&gt;cgrect&lt;/code&gt; just like that, and XCode hasn&amp;#8217;t suggested anything at all. Maybe I have to type more than 6 characters before XCode jumps in? (Nope, that&amp;#8217;s not it.)&lt;/p&gt;

&lt;p&gt;OK well, I&amp;#8217;m done typing now, so I have to fixup this &lt;code&gt;cgrect&lt;/code&gt; by turning it into a real &lt;code&gt;CGRect&lt;/code&gt; with proper caps. Maybe XCode can help with this? I&amp;#8217;ll press &lt;code&gt;ESC&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cl.ly/3N40073R06100R2M1540/screenshot.png"/&gt;&lt;/p&gt;

&lt;p&gt;OK, so I got lucky, it happens to be the 2nd item in the list. (If this list was sorted alphabetically, as it is by default, &lt;code&gt;CGRect&lt;/code&gt; by itself wouldn&amp;#8217;t even be on it). But still, I&amp;#8217;ve written an exact match, shouldn&amp;#8217;t that be what&amp;#8217;s selected by default instead of &lt;code&gt;CGRectInset&lt;/code&gt;? Now I have to fiddle with arrow keys and scrolling and by this point I could have just typed out CGRect myself with proper carpal-tunnel-inducing capitalization and skipped all this business.&lt;/p&gt;

&lt;h3&gt;It gets worse&lt;/h3&gt;

&lt;p&gt;These are just two examples out of many. In fact, XCode&amp;#8217;s completion is so unhelpful that I can only assume the engineers at Apple never have it turned on, and maybe just code everything in Vim anyway. To me, it feels like the sort of feature that was built to &amp;#8220;satisfy&amp;#8221; demand from non-Apple developers. &lt;em&gt;Look, fine, we&amp;#8217;ll give you your &amp;#8216;completion&amp;#8217;, you Microsoft-coddled sissies, now please go away and let us work on OS X 10.7 already!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s just a bit sad for me, because I have tasted the sweet nectar of real, predictable, useful code completion, and it is wonderful and productive. This isn&amp;#8217;t an intractable problem! It just needs some more TLC.&lt;/p&gt;

&lt;p&gt;If you agree with my findings, I encourage, nay, &lt;em&gt;command&lt;/em&gt; you to go fill out a &lt;a href="https://bugreport.apple.com"&gt;bug report&lt;/a&gt; with Apple (they really do read these).&lt;/p&gt;

&lt;p&gt;I have also reposted the issue on &lt;a href="http://openradar.appspot.com/radar?id=154402"&gt;Open Radar&lt;/a&gt;.&lt;/p&gt;</description><link>http://nfarina.com/post/389462700</link><guid>http://nfarina.com/post/389462700</guid><pubDate>Sun, 14 Feb 2010 19:59:00 -0800</pubDate></item></channel></rss>

