<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Clay Allsopp</title>
 <link href="http://clayallsopp.com/atom.xml" rel="self"/>
 <link href="http://clayallsopp.com/"/>
 <updated>2013-05-05T12:20:18-07:00</updated>
 <id>http://clayallsopp.com/</id>
 <author>
   <name>Clay Allsopp</name>
   <email>clay.allsopp@gmail.com</email>
 </author>

 
     
     <entry>
       <title>RubyMotion - Year One</title>
       <link href="http://clayallsopp.com/posts/rubymotion-year-one"/>
       <updated>2013-05-05T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/rubymotion-year-one</id>
       <content type="html">&lt;h1 id=&quot;toc_9250&quot;&gt;RubyMotion: Year One&lt;/h1&gt;

&lt;p&gt;One year ago, &lt;a href=&quot;https://news.ycombinator.com/item?id=3924657&quot;&gt;this post&lt;/a&gt; appeared at the top of Hacker News. It was one of those mysterious moments where the exact thing I was looking for showed up, I kid you not, mere hours after my cranial lightbulb flickered on and illuminated what I wanted: &amp;quot;Ruby for iOS. Bingo.&amp;quot;&lt;/p&gt;

&lt;p&gt;See, I had been exploring projects like &lt;a href=&quot;http://programming.nu/&quot;&gt;Nu&lt;/a&gt; and &lt;a href=&quot;https://github.com/probablycorey/wax&quot;&gt;Wax&lt;/a&gt; and even hacking around JavaScriptCore, trying to find a different path of doing iOS development. The whole Xcode/Objective-C workflow is fine and had worked for years, but compared to how we build web apps something just didn&amp;#39;t sit right. Not so much a &amp;quot;painful&amp;quot; difference that prevented me from getting stuff done, but more of an &amp;quot;awkward&amp;quot; or &amp;quot;uncomfortable&amp;quot; tension that we all kind of go along with because hey, that&amp;#39;s how it&amp;#39;s gotta be, right?&lt;/p&gt;

&lt;p&gt;I guess I wasn&amp;#39;t alone in thinking, &amp;quot;Nope, it doesn&amp;#39;t have to be like that.&amp;quot; I bought RubyMotion on that release day, and I still get that &amp;quot;new software&amp;quot; smell tingling in my nostrils whenever I remember my first attempts at building something for it:&lt;/p&gt;
&lt;p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; align=&quot;center&quot;&gt;&lt;p&gt;Having too much fun with @&lt;a href=&quot;https://twitter.com/rubymotion&quot;&gt;rubymotion&lt;/a&gt; tonight &lt;a href=&quot;http://t.co/aIuY8hNS&quot; title=&quot;http://instagr.am/p/KRvR3cmx_M/&quot;&gt;instagr.am/p/KRvR3cmx_M/&lt;/a&gt;&lt;/p&gt;&amp;mdash; Clay Allsopp (@clayallsopp) &lt;a href=&quot;https://twitter.com/clayallsopp/status/199041325922918400&quot;&gt;May 6, 2012&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;(or yeah, maybe it&amp;#39;s just the funky odor of the place I was living back then.)&lt;/p&gt;

&lt;p&gt;Anyway, it&amp;#39;s now been a year since RubyMotion came to town - what&amp;#39;s happened?&lt;/p&gt;

&lt;p&gt;I think one good visualization is the &lt;a href=&quot;https://github.com/clayallsopp/rubymotion-wrappers/commits/master&quot;&gt;commit history&lt;/a&gt; for the &lt;a href=&quot;http://rubymotion-wrappers.com/&quot;&gt;RubyMotion-Wrappers&lt;/a&gt; site, which is a sort of community-curated database of popular RubyMotion projects. I launched it shortly after the release of RubyMotion with 10 initial projects; since then, it&amp;#39;s quadrupled in size and continues to have steady growth every week. The community has released libraries for everything from &lt;a href=&quot;https://github.com/sxross/MotionModel&quot;&gt;ActiveRecord ports&lt;/a&gt; to &lt;a href=&quot;https://github.com/rubymotion/Joybox&quot;&gt;game engines&lt;/a&gt; to &lt;a href=&quot;https://github.com/mattgreen/elevate&quot;&gt;rethinking how we structure iOS apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;According to RubyGems, the most popular RubyMotion projects are &lt;a href=&quot;http://rubygems.org/gems/sugarcube&quot;&gt;SugarCube&lt;/a&gt; and &lt;a href=&quot;https://github.com/rubymotion/bubblewrap&quot;&gt;BubbleWrap&lt;/a&gt;, which have been downloaded more than &lt;em&gt;50,000 times&lt;/em&gt;. That&amp;#39;s also a fun metric to use as a proxy for how well HipByte (the company behind RubyMotion) is doing, so I don&amp;#39;t think you should worry about them going belly-up any time soon. And if you want to be on the ground-floor of the scene, the &lt;a href=&quot;http://groups.google.com/group/rubymotion&quot;&gt;Google Group&lt;/a&gt; is active with new posts every day.&lt;/p&gt;

&lt;p&gt;We&amp;#39;re using RubyMotion in production &lt;a href=&quot;http://usepropeller.com&quot;&gt;at Propeller&lt;/a&gt;, as are &lt;a href=&quot;http://37signals.com/svn/posts/3432-why-i-loved-building-basecamp-for-iphone-in-rubymotion&quot;&gt;37signals&lt;/a&gt; and several other &lt;a href=&quot;http://blog.rubymotion.com/post/27906866028/rubymotion-success-story-everclip&quot;&gt;award-winning apps&lt;/a&gt;. HipByte continues to be on-top of their game and releasing updates left-and-right: RubyMotion stands at version 1.35, so an update just about every other week for the past year. They were able to ship iOS 6 support &lt;em&gt;within 24 hours&lt;/em&gt; of the beta SDK being released, and I have no fears as to RubyMotion falling being or into deprecation.&lt;/p&gt;

&lt;p&gt;And to be honest, my interpretation of RubyMotion&amp;#39;s first birthday is a little entangled with what I&amp;#39;ve been up to this year. I&amp;#39;ve released more than what most psychologists probably consider a &amp;quot;reasonable&amp;quot; or &amp;quot;healthy&amp;quot; amount of &lt;a href=&quot;https://github.com/clayallsopp?tab=repositories&quot;&gt;open-source projects&lt;/a&gt; for RubyMotion. Plus, I wrote &lt;a href=&quot;http://pragprog.com/book/carubym/rubymotion&quot;&gt;a book&lt;/a&gt; on the thing which has been read and enjoyed by way, way more folks than I had ever dreamed it would.&lt;/p&gt;

&lt;p&gt;Folks still ask about &amp;quot;Rails for iOS,&amp;quot; and if RubyMotion is helping create that. A year later, I think it&amp;#39;s still unclear what even a &amp;quot;Rails for iOS&amp;quot; looks like or what problems it would solve. Mobile development as a whole, RubyMotion or not, is just getting to that age where we&amp;#39;ve seen enough design patterns emerge so we can start to make sense of how everything fits together; in other words, I don&amp;#39;t think can tackle what &amp;quot;Rails for Mobile&amp;quot; looks like until we&amp;#39;ve figured out what a &amp;quot;Basecamp for Mobile&amp;quot; looks like (not to be taken literally).&lt;/p&gt;

&lt;p&gt;At the end of the day, if you don&amp;#39;t like Ruby, if dynamic typing and no compile-time hints are just not your thing, then RubyMotion won&amp;#39;t change your mind. But if you do dig Ruby or Python, or just feel dissatisfied with Xcode and Objective-C, I&amp;#39;m bullish on the future of RubyMotion - the community, the product, and the company.&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     
 
     
     <entry>
       <title>Let Me Tell You A Story</title>
       <link href="http://clayallsopp.com/posts/let-me-tell-you-a-story"/>
       <updated>2013-04-24T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/let-me-tell-you-a-story</id>
       <content type="html">&lt;h1 id=&quot;toc_9244&quot;&gt;Let Me Tell You A Story&lt;/h1&gt;

&lt;p&gt;I&amp;#39;m going to tell you about some stuff that worked for me. Some anecdotes and parables about how I got from point A to point B. It&amp;#39;ll be light on hard data and analysis, and it&amp;#39;ll probably hinge on one or two key but seemingly controversial decisions I made. I&amp;#39;m confident my self-crafted narrative will make you pull a one-eighty with regards to whatever it is you&amp;#39;re doing.&lt;/p&gt;

&lt;p&gt;I feel pretty strongly about these tidbits of advice, probably even a little attached to them. You see, all of my recent success is solely due to this simple collection of ideas. Although I&amp;#39;m distilling and funneling years of experience into a few quick bulletpoints, I promise they&amp;#39;re the only thing that separates you and me.&lt;/p&gt;

&lt;p&gt;And you&amp;#39;ll read and nod and think, &amp;quot;Yeah, y&amp;#39;know, I can believe that, this guy sounds reasonable enough.&amp;quot; And you&amp;#39;ll Tweet it and Like it and Pin it and Snapchat it and everything else, because it&amp;#39;s the kind of information you think everyone should know.&lt;/p&gt;

&lt;p&gt;But then there will be others who disagree and think I&amp;#39;m absolutely full of it. These folks, in comments or in their own writing, will literally tell you to do the &lt;em&gt;exact opposite&lt;/em&gt; of what I&amp;#39;m saying. They&amp;#39;ll share their own stories and come to conclusions which are flat-out contradictory to mine, which just confuses the hell out of you.&lt;/p&gt;

&lt;p&gt;Because in what universe can this other well-respected fellow and I both be correct? More practically, how in the world can you take either of us seriously and do something with our ideas?&lt;/p&gt;

&lt;p&gt;You might defer to me, sending a message like, &amp;quot;Hey Clay, Other Person thinks you&amp;#39;re wrong, what&amp;#39;s up with that?&amp;quot; And I&amp;#39;ll read through the rebuttal and make some &amp;quot;clarification&amp;quot; stating how that is a special case, while also slightly refining my own position to stay correct. But at the end of the day, it&amp;#39;s basically a wishy-washy non-answer and I save face by maintaining that I&amp;#39;m still right.&lt;/p&gt;

&lt;p&gt;A couple of days have pass, and where are you now? You&amp;#39;ve read some blog posts, sent out a few Tweets and Likes to grab the authors more followers, but you are basically back where you started. The social-media-information-entropy cycle.&lt;/p&gt;

&lt;p&gt;So, anyway, what&amp;#39;s my story?&lt;/p&gt;

&lt;p&gt;That no ancedote will always hold true, no nugget of advice will always be set in stone, there will be counter-examples to every real-world observation, and that there are no platitudes (heh). Times and trends change; what&amp;#39;s important is that you choose an idea quickly and be able to change your mind just as fast. Strong opinions, loosely held.&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     
 
     
     <entry>
       <title>The Purple Crayon</title>
       <link href="http://clayallsopp.com/posts/harold-and-the-purple-crayon"/>
       <updated>2013-03-17T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/harold-and-the-purple-crayon</id>
       <content type="html">&lt;h1 id=&quot;toc_9241&quot;&gt;The Purple Crayon&lt;/h1&gt;

&lt;p&gt;There&amp;#39;s this book, &lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Harold_and_the_Purple_Crayon&quot;&gt;Harold and the Purple Crayon&lt;/a&gt;&lt;/em&gt;, that I just obsessed over as a kid.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s the story of a boy named Harold and the namesake crayon, and how one night he decides to go on a moonlight stroll. But there&amp;#39;s one small dilemma: he lacks a moon. So how does he solve his problem? Well, Harold simply goes and makes a moon using his crayon.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/kMxxuj3.jpg&quot; alt=&quot;Harold sketching a moon&quot;&gt;&lt;/p&gt;

&lt;p&gt;He continues to sketch himself into all sorts of adventures, like accidentally doodling an ocean and scribbling an emergency balloon mid-free fall. Harold keeps scratching his own itches and solving his (mostly self-concocted) problems using nothing more than the wax tool at his disposal and a bit of creativity.&lt;/p&gt;

&lt;p&gt;The book has a simple premise, but something about it just kept me reading ad infinitum. I was stuck to it in that wonderful way kids can repeat something endlessly without any diminishing amusement or happiness.&lt;/p&gt;

&lt;p&gt;Why? Because &lt;em&gt;The Purple Crayon&lt;/em&gt; is, at its heart, a book about building things. About taking some idea in your head, something you want exist in the world, and making it happen. And by using the lowly crayon, rather than a computer or mechanical tools or complex math, it makes a kid feel that they really can create something. It&amp;#39;s a glimpse of a world where your ideas are just one step shy of tangible.&lt;/p&gt;

&lt;p&gt;But timing is everything: published in 1955, the book predates the web and all of personal computing by a couple of decades, and even beat plastic interlocking Legos by a couple of years. As a kid the 1950s, solving your own problems was decidedly a game of imagination over implementation: you could draw, write, and talk about what you would make all day long, but actually crafting something useful was pretty much left to the grown-ups. Then along came computers.&lt;/p&gt;

&lt;p&gt;Coding democratized how we can solve our own problems, regardless of age. By the time I was toddling around, building websites in elementary school wasn&amp;#39;t uncommon; when I got older, teenagers were starting companies in their dorm rooms that would grow into generation-defining entities.&lt;/p&gt;

&lt;p&gt;So maybe the radical notion of a kid creating a moon, or at least space travel, isn&amp;#39;t so far-fetched: it&amp;#39;s just that we&amp;#39;d be using a &lt;em&gt;Purple Keyboard&lt;/em&gt;. If you want something to exist, all you need might be a little leap from crayons to code.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Google Reader - A Product vs. A Symbol</title>
       <link href="http://clayallsopp.com/posts/google-reader-product-vs-symbol"/>
       <updated>2013-03-15T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/google-reader-product-vs-symbol</id>
       <content type="html">&lt;h1 id=&quot;toc_9240&quot;&gt;Google Reader: A Product vs. A Symbol&lt;/h1&gt;

&lt;p&gt;Google Reader, the product, died and should serve as a lesson in missed opportunities. But the loss of Google Reader, the symbol, should be grieved for and contemplated with many furrowed eyebrows.&lt;/p&gt;

&lt;p&gt;Google Reader came out in 2005, before the iPhone, Android, and the ubiquity of smartphones. Before Twitter, Facebook, and Tumblr. It had a half-decade head start on Flipboard and Prismatic.&lt;/p&gt;

&lt;p&gt;But it became a dinosaur. It was a desktop web product living in an age where we consume our content leaning around at bus stops or looking busy at awkward parties. Apps like Reeder and Press took the charge on nailing the user experience of reading feeds on-the-go; they grew, evolved, and established brands independent of and stronger than Google Reader. And they will live on after Reader&amp;#39;s final breath.&lt;/p&gt;

&lt;p&gt;Then came Flipboard, Prismatic, and all the other content discovery platforms that became smarter than just Google Reader in lipstick. They have impeccable design, strong brands, and are mainstream &amp;quot;things&amp;quot; in a way Google Reader never was (maybe partly due to Apple&amp;#39;s  &lt;a href=&quot;http://inside.flipboard.com/2010/12/09/apple-picks-flipboard-as-app-of-the-year/&quot;&gt;high visibility endorsements&lt;/a&gt;). Despite building on top of the exact same web feed technologies as Reader, they created better browsing and recommendation experiences across the web, mobile, and the newborn content-havens of tablets.&lt;/p&gt;

&lt;p&gt;Google Reader, the product, seems to be a textbook example of how an incumbent failed to head where the puck was going. But maybe where the puck went really isn&amp;#39;t so great.&lt;/p&gt;

&lt;p&gt;Google Reader is a symbol of a time just before the Yet-Another Rise Of The Wall Gardens; when the web looked to be on the verge of more semantic and open rather than proprietary; where information was becoming easily accessible and machine-readable instead of more locked up and fragmented.&lt;/p&gt;

&lt;p&gt;Today, news and blog content is relatively open and parseable because of RSS and Google Reader&amp;#39;s leverage, but all the recent social information about ourselves is locked behind protocols unique to each website and app. Google Reader did &lt;a href=&quot;http://corte.si/posts/socialmedia/rip-google-reader.html&quot;&gt;some damage&lt;/a&gt; to this cause of &amp;quot;openness&amp;quot;, but it should remind us of a time before Twitter and Facebook swallowed our capacity for consumption and threw away the key.&lt;/p&gt;

&lt;p&gt;I get why Google finally killed Reader. It was essentially free infrastructure and storage for an ecosystem of apps that generated more value (both financial and intangible) than the product itself. Google shouldn&amp;#39;t be in the business of doing non-business, and it makes sense to turn off the lights. But it&amp;#39;s another sign that we&amp;#39;ve entered a darker timeline in the history of the net, where information is becoming even more closed and out of reach.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Where The Puck Is Going</title>
       <link href="http://clayallsopp.com/posts/where-the-puck-is-going"/>
       <updated>2013-03-01T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/where-the-puck-is-going</id>
       <content type="html">&lt;h1 id=&quot;toc_9239&quot;&gt;Where The Puck Is Going&lt;/h1&gt;

&lt;p&gt;Mouse-and-keyboard are dead. Touch is dying. Post-touch is coming. Hyperbole? Maybe, but probably not.&lt;/p&gt;

&lt;p&gt;See, about a year ago Gabe Newell talked about &lt;a href=&quot;http://venturebeat.com/2012/07/25/valves-gabe-newell-talks/&quot;&gt;the future of gaming&lt;/a&gt;, and he not just illuminated my own cranial lightbulb but basically tossed a flash-bang grenade in its place:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[Mouse and keyboard were] stable for about 25 years. I think touch will be stable for about 10 years. I think post-touch, and we’ll be stable for a really long time — for another 25 years. I think touch will be this intermediate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe it was the way he phrased it, or maybe just what I had for breakfast that day, but by the end of that sentence everything seemed to make sense. The shift from mouse to touch to this &lt;em&gt;thing&lt;/em&gt; Gabe calls &amp;quot;post-touch&amp;quot; appeared calculated, logical, and inevitable.&lt;/p&gt;

&lt;p&gt;Why? In my mind, it clicked that that we&amp;#39;re always inching closer to computing being &amp;quot;do what I really mean.&amp;quot;&lt;/p&gt;

&lt;p&gt;Before GUIs, computing was &amp;quot;type these commands and do what they state.&amp;quot; That works, but you could easily type something different from what you actually want (as engineers are often reminded). And then after GUIs, we gained some more fidelity: something like moving a desktop folder meant &amp;quot;move the folder in the same direction as this mouse-device-thing.&amp;quot; If you moved left, the folder went left.&lt;/p&gt;

&lt;p&gt;Now, in the touch-era, it&amp;#39;s more like &amp;quot;move the folder where my finger goes,&amp;quot; without any mouse-indirection happening. But with post-touch, the status quo will be &amp;quot;move the folder where I&amp;#39;m looking&amp;quot; or &amp;quot;where I say&amp;quot;; and one day (as Kurzweilian as this sounds) it&amp;#39;ll be &amp;quot;move it where I&amp;#39;m thinking.&amp;quot; Or simply &amp;quot;move it.&amp;quot;&lt;/p&gt;

&lt;p&gt;And here we are, not even a full year after Gabe&amp;#39;s talk, and the first post-touch products are already landing on Planet Earth: Glass, Myo, Leap Motion, Kinect, on and on. This stuff just creeps up on us; only six years ago &lt;a href=&quot;http://images.tmcnet.com/tmc/misc/articles/Image/2012/razroriginal.jpg&quot;&gt;this&lt;/a&gt; was the end-all-be-all of mobile &amp;quot;computing&amp;quot;.&lt;/p&gt;

&lt;p&gt;Touch devices cannibalized laptops and desktops, and you can bet that the new generation of post-touch products will gnaw away at smartphones and tablets. And it&amp;#39;s exciting to think about what that future holds: what do things that replace our phones even &lt;em&gt;look like&lt;/em&gt;? Will it be glasses? Or watches? Will it be made by Apple or Google, or a new player? Will it be as &lt;a href=&quot;http://vimeo.com/46304267&quot;&gt;sci-fi&lt;/a&gt; as we imagine?&lt;/p&gt;

&lt;p&gt;The abstractions between our intentions and how we execute them in computing are eroding. That&amp;#39;s where the &lt;a href=&quot;http://www.complex.com/tech/2012/10/steve-jobs-quotes/move-toward-the-goal&quot;&gt;puck is going&lt;/a&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Why There Are No Game Console App Stores</title>
       <link href="http://clayallsopp.com/posts/why-there-are-no-console-app-stores"/>
       <updated>2013-02-21T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/why-there-are-no-console-app-stores</id>
       <content type="html">&lt;h1 id=&quot;toc_9238&quot;&gt;Why There Are No Game Console App Stores&lt;/h1&gt;

&lt;p&gt;At yesterday&amp;#39;s Playstation 4 announcement, Sony kept hammering home how just unimaginably fantastic the PS4 is for developers. And they&amp;#39;re right: the new x86 architecture is definitely a more familiar environment than the &lt;a href=&quot;http://bit.ly/7SFy3&quot;&gt;exotic Cell&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But the whole time I sat there thinking, &amp;quot;Developers, right, got it. So when are they going to announce the PS4 SDK and App Store for smaller guys?&amp;quot;&lt;/p&gt;

&lt;p&gt;It never came. I watched all those folks come on stage and talk about how great the new Playstation is for them, and they even had Jonathan Blow show up to fill his almost obligatory place as indie ambassador, but they never did announce an App Store that normal programmers like me could take a shot at.&lt;/p&gt;

&lt;p&gt;It wouldn&amp;#39;t have been unexpected. When the Apple App Store was first announced in 2008, to me it seemed like a no-brainer for console makers to follow up with their own version. Five years later, Apple has &lt;em&gt;hundreds of thousands&lt;/em&gt; of products in its store, and by far the most popular of which are...games. That&amp;#39;s proof enough that consumers, non-traditional gamers especially, will download games from a marketplace in droves.&lt;/p&gt;

&lt;p&gt;But it never happened on the consoles. Microsoft had an Indie Games store, but it was &lt;a href=&quot;http://www.reddit.com/r/Games/comments/18irx0/the_minecraft_test_how_to_tell_if_your_console_is/c8fpb5k&quot;&gt;notoriously disregarded&lt;/a&gt; and under-promoted. Sony and Nintendo remained gardens with high, high walls. Why does this make sense for them?&lt;/p&gt;

&lt;p&gt;The problem is money. Console hardware is generally sold at a loss or at cost; the producers make their profits from software. This includes fees and licensing from conventional boxed games, paid DLC and expansions, media and content sales, and (increasingly) advertising. Those are in a rough sort of descending order; boxed games are especially great for Microsoft et al because they&amp;#39;re expensive and relatively hands-off.&lt;/p&gt;

&lt;p&gt;But when you&amp;#39;ve got an App Stores, you&amp;#39;ve got a race to the bottom. Even if you artificially impose a price floor of something like $9.95, that&amp;#39;s still $50 cheaper than the latest Halo. Given enough time, some developer will make a great looking and popular game at that low price point (or, more likely, for free) and lots of people will start to wonder, &amp;quot;Are Halo 5/KillZone/Zelda &lt;em&gt;really&lt;/em&gt; worth $60?&amp;quot; And as soon as that idea is incepted into consumer&amp;#39;s collective subconscious, all those big-ticket games start looking more like dinosaurs. The market becomes bimodal: either you&amp;#39;re a massive AAA-budget game like Halo, or you&amp;#39;re a low-cost indie game.&lt;/p&gt;

&lt;p&gt;Console makers are already being faced with three new (and cheaper) developments in that direction: the OUYA, the Steam Box, and the lingering specter of Apple properly entering the space with an Apple TV SDK. These folks might not get giant Call of Duty-class exclusives, but they&amp;#39;ll get more than enough independent games and apps to stay competitive on on their bottom line.&lt;/p&gt;

&lt;p&gt;So what was the vibe I got from the PS4 announcement? More of the same. The market is evolving, and Microsoft, Sony, and Nintendo will eventually have to cannibalize themselves to keep up. And while Sony didn&amp;#39;t announce anything radical yesterday, and Microsoft&amp;#39;s plans are still unknown, both still have time to change the game.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>How A Pull Request Rocked My World</title>
       <link href="http://clayallsopp.com/posts/the-story-of-pull-request"/>
       <updated>2013-02-02T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/the-story-of-pull-request</id>
       <content type="html">&lt;h1 id=&quot;toc_9237&quot;&gt;How A Pull Request Rocked My World&lt;/h1&gt;

&lt;p&gt;This is a story about Pull Request #2 and how it made me rethink my code. This isn&amp;#39;t really a story about the code itself; it&amp;#39;s about how even a small refactoring can multiply value and productivity. But hey, let&amp;#39;s not get ahead of ourselves.&lt;/p&gt;

&lt;p&gt;Long ago, there was some code in an iOS library called &lt;a href=&quot;https://github.com/clayallsopp/formotion&quot;&gt;Formotion&lt;/a&gt; that looked like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;submit_button?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;make_submit_cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchable?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;make_switch_cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checkable?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;make_check_cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editable?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;make_text_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Basically, it configures this &lt;code&gt;cell&lt;/code&gt; object based on properties of the &lt;code&gt;row&lt;/code&gt;. That serpentine &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elsif&lt;/code&gt; chain did the trick and didn&amp;#39;t seem alarmingly unreasonable at the time, so the code shipped with the first version of Formotion. It all worked out, the project got some watchers and star-ers, and folks generally had great feedback. All was well.&lt;/p&gt;

&lt;p&gt;But then &lt;a href=&quot;https://github.com/clayallsopp/formotion/pull/2&quot;&gt;this little pull request&lt;/a&gt; appears a few days later.&lt;/p&gt;

&lt;p&gt;I get an email about it, and am immediately excited because hey, someone liked my little project enough to contribute! So I command-click the link open in a new tab and have a look.&lt;/p&gt;

&lt;p&gt;The request is labeled &lt;strong&gt;Refactoring &amp;amp; Multiline Text Type.&lt;/strong&gt; So usually when someone comes up to you and says like, &amp;quot;Hey I did some refactoring, check it out,&amp;quot; the implicit understanding is that the original thing just wasn&amp;#39;t so hot. And about nine times out of ten you agree and know that it&amp;#39;s true, but it is a little awkward when someone beats you to fixing it.&lt;/p&gt;

&lt;p&gt;Anyway, I inhale whatever pride I have about my work and click the &amp;quot;Files Changed&amp;quot; tab to investigate. I take a gander, and basically what the request does is replace that big fat &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elsif&lt;/code&gt; block with this one line:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Whoa, what is this new &lt;code&gt;row.object&lt;/code&gt;? Well, elsewhere in the refactor, this line appeared:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Formotion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RowType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;What&amp;#39;s all this about? Turns out that the refactor took the various row configurations (&lt;code&gt;switch&lt;/code&gt;, &lt;code&gt;submit&lt;/code&gt;, &lt;code&gt;check&lt;/code&gt;) and created new subclasses of &lt;code&gt;Formotion::RowType&lt;/code&gt; for each: &lt;code&gt;SwitchRow&lt;/code&gt;, &lt;code&gt;SubmitRow&lt;/code&gt;, &lt;code&gt;CheckRow&lt;/code&gt;, etc. In those objects, the &lt;code&gt;build_cell&lt;/code&gt; method now dictates how the &lt;code&gt;cell&lt;/code&gt; is configured, taking the place of the old &lt;code&gt;make_submit_cell&lt;/code&gt; methods.&lt;/p&gt;

&lt;p&gt;And that &lt;code&gt;RowType.for()&lt;/code&gt; method? It actually does a little metaprogramming to grab the appropriate subclass:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# type == :switch or :submit etc&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;downcase&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_row&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;camelize&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# string == &amp;#39;SwitchRow&amp;#39;, &amp;#39;SubmitRow&amp;#39; etc&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Formotion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RowType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So instead of some &lt;code&gt;if&lt;/code&gt; tree and hard-coded methods, everything is dynamic and decided at run-time. You can reuse code with inheritance. Absolutely crazy. Brilliant.&lt;/p&gt;

&lt;p&gt;All of this blew me away. Like this &amp;quot;@mordaroso&amp;quot; fellow strolled on up, cocked his knee skyward, and jettisoned his leg into the rickety wooden door that previously sheltered my mind.&lt;/p&gt;

&lt;p&gt;So there I am, hunched over my laptop, eyebrows furrowed to the point where my forehead like folds in over itself, just stupefied by this code. And the ramifications, like how it allows for extensibility and plugins and testing and a generally more robust codebase, are just gushing into the void Fabio Kuhn exposed in said cranium.&lt;/p&gt;

&lt;p&gt;With just that one refactor, the value of my little library had grown tremendously! If you wanted to make a plugin, there was no messy monkey-patching: simply create your new &lt;code&gt;RowType&lt;/code&gt; subclass, like &lt;code&gt;MyWidgetRow&lt;/code&gt;, and you&amp;#39;re done. It just works.&lt;/p&gt;

&lt;p&gt;Not a day goes by where I&amp;#39;m shin-deep in a project and don&amp;#39;t think about what that pull request revealed: reorganizing your code (in the right way) can create cascading growth in productivity and value. In Formotion&amp;#39;s case, that pattern of dynamic-class-lookup is now used in other parts of the codebase and allows for a project-wide plugin architecture. Big win all around. This sort of stuff really is worth being diligent about.&lt;/p&gt;

&lt;p&gt;So thanks, &lt;a href=&quot;http://twitter.com/mordaroso&quot;&gt;Fabio&lt;/a&gt;, for blowing my mind.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit 2/3/2013&lt;/em&gt; So a lot of folks drew attention to &amp;quot;You can reuse code with inheritance. Absolutely crazy. Brilliant.&amp;quot; and took as equivalent to me saying &amp;quot;It&amp;#39;s absolutely crazy and brilliant you can reuse code with inheritance.&amp;quot; I get that both in- and especially out-of-context that&amp;#39;s how it comes off, but it&amp;#39;s not what I meant. It was sloppy and I should&amp;#39;ve been more careful in writing.&lt;/p&gt;

&lt;p&gt;I meant it to come off more like &amp;quot;...everything is dynamic and decided at run-time, plus you get a great plugin architecture if you do some polymorphic tricks with these &lt;code&gt;RowType&lt;/code&gt; objects. And all of these benefits came from just one simple refactoring. The power of small refactors is absolutely crazy. Brilliant.&amp;quot; See &lt;a href=&quot;http://news.ycombinator.com/item?id=5160287&quot;&gt;my comment&lt;/a&gt; for more context.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Growing Old on Facebook</title>
       <link href="http://clayallsopp.com/posts/mirror-mirror"/>
       <updated>2012-12-22T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/mirror-mirror</id>
       <content type="html">&lt;h1 id=&quot;toc_9236&quot;&gt;Growing Old on Facebook&lt;/h1&gt;

&lt;p&gt;There&amp;#39;s an entire generation where every photo, message, post, idea between adolescence and adulthood is cataloged on Facebook. Just click on the most recent picture and tap your left arrow key to see.&lt;/p&gt;

&lt;p&gt;Wrinkles vanish, beards recede, and bodies contract and expand into the past. There&amp;#39;s all the embarrassing haircuts, forgotten friends, parties, love, heartbreak, it&amp;#39;s all there waiting to be rediscovered. New moments pile up every day, just itching for our future selves to find again.&lt;/p&gt;

&lt;p&gt;And more than the photos, there&amp;#39;s also the way we talked, the jokes we made, all the effortless things that were once second-nature but now look a bit alien. Things we factually know we said, but for the life of us can&amp;#39;t figure out how it came out of our mouths. Maybe for other generations these were glimpsed in diary scraps or old letters, but now it&amp;#39;s just...there, on Facebook, digitally frozen in time.&lt;/p&gt;

&lt;p&gt;You can message someone you haven&amp;#39;t spoken with in years, and yet it visually flows right under some unimaginably unrelated conversation from 2007. And when you realize that exact numerical gap between the years, it stings a little. Reading how you&amp;#39;ve changed, how they&amp;#39;ve changed, and thinking about everything that didn&amp;#39;t happen in-between.&lt;/p&gt;

&lt;p&gt;These experiences and emotions are unprecedented. We&amp;#39;re on the precipice of something new and unknown, but undoubtedly permanent, in the human condition. It was never this easy or this obvious to see how we&amp;#39;ve grown, or how our friends came and went out of our lives. We can reconstruct our past and evolution with such incredible detail, but at the same time there&amp;#39;s just a tinge of sadness...&lt;/p&gt;

&lt;p&gt;It might not forever be on Facebook or Twitter or whatever else becomes popular, but the progress of the internet will not cease. These pristine reflections of our former selves will live on in the tombs of archived data; they will outlive us.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/epbOr.jpg&quot; alt=&quot;Me, 2006, via Facebook&quot;&gt;&lt;/p&gt;
&lt;p style='text-align:center'&gt;&lt;em&gt;Me, 2006, via Facebook
&lt;/em&gt;&lt;/p&gt;</content>
     </entry>
     
 
     
     <entry>
       <title>Web Views Are Green Screen</title>
       <link href="http://clayallsopp.com/posts/web-views-are-green-screen"/>
       <updated>2012-12-19T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/web-views-are-green-screen</id>
       <content type="html">&lt;h1 id=&quot;toc_9235&quot;&gt;Web Views Are Green Screen&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/biXdr.jpg&quot; alt=&quot;Lord of the Rings Set&quot;&gt;&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the set of Lord of the Rings, taken around twelve years ago. Even a decade later, these films have hardly aged a day, mainly due to what is evident from this photo: beautifully designed set pieces. The relatively early computer graphics of the time are (with the exception of Gollum) rarely front-and-center, as the production opted for a real-life, intricately crafted world using as little green screen as possible.&lt;/p&gt;

&lt;p&gt;And a decade later, you just don&amp;#39;t find this kind of movie set anymore. Instead, we get last two Star Wars prequels, filmed in giant green and blue boxes.&lt;/p&gt;

&lt;p&gt;In moderation, green screen works wonderfully, drawing us further into the film&amp;#39;s world and breathing life into the impossible; at its worst, digital meddling is jarring and actually takes us out of the experience, making us wonder, &amp;quot;Oh yeah, that&amp;#39;s not real.&amp;quot; And then we&amp;#39;re no longer thinking about the characters or the story: we&amp;#39;re thinking about the fact that this is a movie, and those are computer graphics.&lt;/p&gt;

&lt;p&gt;The same holds true for the web views we often embed in mobile apps: executed when necessary and with great skill, they can actually create a better user experience. But when we fudge them up, as we often do in these nascent days of mobile development, it breaks the illusion and users are left thinking, &amp;quot;Hmm, why doesn&amp;#39;t this bit work like everything else?&amp;quot; And then our users aren&amp;#39;t thinking about their original purpose of opening the app: they&amp;#39;re considering the technology and pondering why it doesn&amp;#39;t feel quite right.&lt;/p&gt;

&lt;p&gt;George Lucas and many other filmmakers embraced the digital, green-screen-everything revolution in part because it meant a less cumbersome and more flexible process: no rolls of film to worry about, and if you&amp;#39;re not sure how to design a set right now then it can all be changed in post-production. Sound familiar? Sort of like, &amp;quot;No Objective-C or Java to compile! We can change at any time from the server!&amp;quot;&lt;/p&gt;

&lt;p&gt;The temptation with web views is our ability to change things without an additional app approval cycle, and that ability can be a practical requirement or strategic advantage. But it comes at the risk of making that part of the product feel unnatural, especially given how precisely a web view needs to be programmed to make it look-and-feel native. And the more upfront your app is with its web views, the more obvious it will probably become. Just like bad green screen effects.&lt;/p&gt;

&lt;p&gt;Those are the risks...but there is also another way. Pixar films are entirely computer-generated, which means nothing looks out-of-place and our brains aren&amp;#39;t busy thinking, &amp;quot;This part is real but that bit over there is fake.&amp;quot; This is why WebOS was so promising: its third-party apps felt natural because, despite being just HTML and CSS, everything else the user interacted with on the device was also a just web page! There wasn&amp;#39;t a destination between &amp;quot;web&amp;quot; and &amp;quot;native&amp;quot;: it was all the same.&lt;/p&gt;

&lt;p&gt;Maybe that&amp;#39;s why it&amp;#39;s such a tragedy that WebOS didn&amp;#39;t take off, or that Google has pushed Android onto millions of devices instead of a mobile version of Chrome OS. For one reason or another, web-browser operating systems just haven&amp;#39;t taken off, and that means native software will continue to be a better solution when forming the ideal user experience. Just like hand-crafting films will yield more timeless results than giant green boxes.&lt;/p&gt;

&lt;p&gt;At the end of the day, after the lights turn off and the actors have left, all the special effects in the world won&amp;#39;t prevent you from making a bad movie. Whether we&amp;#39;re producing motion pictures or mobile apps, we&amp;#39;re telling stories, trying to create something people care about with nothing but our minds and our hands. And if our core idea just doesn&amp;#39;t work, then no amount of digital sugar-coating will save it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.themovieblog.com/wp-content/uploads/2009/06/lucas-green-screen.jpg&quot; alt=&quot;George Lucas&quot;&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>We're Better At Design, And That's Not Good</title>
       <link href="http://clayallsopp.com/posts/better-at-design"/>
       <updated>2012-12-15T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/better-at-design</id>
       <content type="html">&lt;h1 id=&quot;toc_9234&quot;&gt;We&amp;#39;re Better At Design, And That&amp;#39;s Not Good&lt;/h1&gt;

&lt;p&gt;Everyone is getting frighteningly good at visual design. The skills dispersed, our hardware improved, pixels shrank, and big companies began putting muscle behind their Dribbble stars. Every year, without fail: more, better, and easier. The last decade had some missteps, but overall a greater proportion of software just got really damn good-looking. And that kind of worries me a little.&lt;/p&gt;

&lt;p&gt;It worries me that really good visual design is becoming commonplace. It used to be that you could just glance at a website and get a quick feel for its quality and recency just from its visual identity; look at Facebook versus Myspace, or Svbtle versus Wordpress. Visual design can add important interaction cues and serve a greater purpose than eye candy, but its role in branding shouldn&amp;#39;t be underestimated.&lt;/p&gt;

&lt;p&gt;And over the past few months, I noticed most newborn products look fantastic from day one. It could be from Bootstrap, or readymade iOS templates, or a better freelancer they found on Scoutzie, or 99Designs, or whatever; there are now a myriad of methods you can use to launch your service and make it look great for cheap or even free.&lt;/p&gt;

&lt;p&gt;So what&amp;#39;s wrong with that? The problem is we judge books by their covers. We&amp;#39;re more likely to pick the prettiest object up first.&lt;/p&gt;

&lt;p&gt;I know someone might shout, &amp;quot;No! The important part isn&amp;#39;t the visuals, it&amp;#39;s all about the interactions and the core product!&amp;quot; And that&amp;#39;s exactly right; but to get a feel for those deeper aspects you need to spend time with it, and we usually don&amp;#39;t have that time. People decide whether the phone they might buy sucks based on a few minutes of noodling, and that impression is dominated by the graphics and flashy animations. And consider the app economy without free trials, where the only thing you see in search results is a few carefully picked screenshots. &lt;/p&gt;

&lt;p&gt;When everything moves toward beautiful, it chips away at our &amp;quot;product survival&amp;quot; instinct and makes it harder for us to tell the gold from the crap. We could be looking at a dangerous, privacy-invasive service and still have some trust because it&amp;#39;s wrapped in lickable buttons and subtle gradients. Or you could be walking down the grocery aisle and pick an unhealthy cereal basically made of high-fructose corn syrup because the box made good use of whitespace and a bold sans-serif font. What was once our compass for quality now points in every direction.&lt;/p&gt;

&lt;p&gt;That doesn&amp;#39;t mean we should drop everything and make plain, styleless software again. Instead, we need to remember it&amp;#39;s an arms race: you use TypeKit, they license directly; you spend $5,000 on an icon, they hire an entire consulting firm. More impressive visuals will offer diminishing returns against competition.&lt;/p&gt;

&lt;p&gt;So what&amp;#39;s the solution? Just make sure your product doesn&amp;#39;t look terrible, and then move on. Build the things people care about, talk to your customers, and iterate. There is no silver, reflective, radial-gradient bullet to success.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Writing a Programming Book</title>
       <link href="http://clayallsopp.com/posts/writing-a-programming-book"/>
       <updated>2012-12-12T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/writing-a-programming-book</id>
       <content type="html">&lt;h1 id=&quot;toc_9233&quot;&gt;Writing a Programming Book&lt;/h1&gt;

&lt;p&gt;It&amp;#39;s barely past midnight on Christmas, and there&amp;#39;s a book on my lap. Its black glossy cover smears with every brush of my fingers. Front and center, the lone graphic is half of a sliced, juicy grapefruit. That “new book” smell eases from the unworn pages. The book is &amp;quot;Beginning iPhone Development&amp;quot; by Dave Mark and Jeff LaMarche, and it changed everything for me.&lt;/p&gt;

&lt;p&gt;So here I am years later, just finished writing &lt;a href=&quot;http://pragprog.com/book/carubym/rubymotion&quot;&gt;my own iOS book&lt;/a&gt;. It&amp;#39;s hard not to wonder if there&amp;#39;s an aspiring programmer who might connect with my work like I did with Dave and Jeff&amp;#39;s. That maybe my little RubyMotion book might show them, &amp;quot;Yeah, it really &lt;em&gt;is&lt;/em&gt; this easy to build something cool&amp;quot;; but then again, almost every other book I read failed to do that.&lt;/p&gt;

&lt;p&gt;There are as many different ways to write a programming book as there are programmers. There are those reference tomes, the kinds of things that sputter dust when you manage to wrangle them onto the desk. Then there&amp;#39;s the cookbooks, textbooks, the career guides, the list goes on. But growing up I collected dozens of the venerable &amp;quot;Getting Started&amp;quot; genre, and that&amp;#39;s what I wanted to do for RubyMotion.&lt;/p&gt;

&lt;p&gt;Writing that kind of introduction is tricky. You risk stonewalling your readers to the point where they flip the table and walk away, never giving the technology the chance you believe it deserves. In my experience, those books usually have an authoritative or even aloof tone, and focus heavily on demonstrating &amp;quot;the right way.&amp;quot; But the right way to engineer a project might be the wrong way to get excited about it.&lt;/p&gt;

&lt;p&gt;I made my priority to get something &lt;em&gt;cool&lt;/em&gt;, but simple, on the reader&amp;#39;s screen as fast as possible, and then worry about cleaning up any mess a little later. For example, iOS books usually start off with how to use Interface Builder or setting up &lt;code&gt;UIViewController&lt;/code&gt;s, but that&amp;#39;s just so much overhead to getting anything interesting on the screen. I bucked tradition and began with code I&amp;#39;d never use in production: adding blue boxes straight on the app&amp;#39;s &lt;code&gt;UIWindow&lt;/code&gt;. It&amp;#39;s a bit dirty, but then we can quickly jump into buttons, animations, text boxes, and really start to make fun apps.&lt;/p&gt;

&lt;p&gt;Technical reviewers noted that exact decision, and then expressed their delight at how well it actually worked. And to me, that&amp;#39;s what a &amp;quot;Getting Started&amp;quot; book is about: here&amp;#39;s the bare-minimum, and now here&amp;#39;s cool stuff we can do with that. As long as you keep that thesis in mind, the rest of the writing is just filling in gaps.&lt;/p&gt;

&lt;p&gt;So, if you&amp;#39;re in the market to very quickly become up-to-speed on iOS development, then join me in making cool projects with &lt;em&gt;&lt;a href=&quot;http://pragprog.com/book/carubym/rubymotion&quot;&gt;RubyMotion: iOS Development With Ruby&lt;/a&gt;&lt;/em&gt;. Or if you think this is all a rubbish idea, ping me &lt;a href=&quot;http://twitter.com/clayallsopp&quot;&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>So, What Do You Do All Day?</title>
       <link href="http://clayallsopp.com/posts/what-do-you-do-all-day"/>
       <updated>2012-12-02T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/what-do-you-do-all-day</id>
       <content type="html">&lt;h1 id=&quot;toc_9232&quot;&gt;&amp;quot;So, what do you do all day?&amp;quot;&lt;/h1&gt;

&lt;p&gt;There&amp;#39;s the sounds. Or, more often, the lack of sound. No crescendos or variation, but just intermittent spurts of either furious clicking or — nothing at all. Repeating, hundreds of times each day. From the repetitive, almost rhythmic tapping to —. Just an abrupt, knife-like silence.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s uncomfortable, struggling silence. It could be any mix of confusion, frustration, or just bewilderment, lasting longer than any given torrent of keyboard noise. And, as trite as this sounds, it really can be deafening. The longer it grows, well, the harder it is to overcome.&lt;/p&gt;

&lt;p&gt;And in those lingering silences, I&amp;#39;ll wait. Probably a little hunched, maybe cradling my chin in one contortion or another, but still silent. Get up, walk around, make some tea, all trying to coax a little inspiration out of my subconscious.&lt;/p&gt;

&lt;p&gt;We romanticize our authors and envision the constant clicking of their typewriters, but I like to imagine they had their quieter moments too. That it wasn&amp;#39;t always so perfect and picturesque, but that it was hard and took work. That sometimes their initial excitement extinguished...but at the end of the day it was rekindled.&lt;/p&gt;

&lt;p&gt;And eventually, the silence does end. Whether by a genuine solution or by the brute, angry force of my own frustration, the rapid clicking resumes. And somehow, the sum of all these clicks and all their gaps creates something I set out to make.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>How It Feels To Build</title>
       <link href="http://clayallsopp.com/posts/how-it-feels-to-build"/>
       <updated>2012-11-25T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/how-it-feels-to-build</id>
       <content type="html">&lt;h1 id=&quot;toc_9231&quot;&gt;How It Feels To Build&lt;/h1&gt;

&lt;p&gt;It starts with an idea, and then we plunge an arm into the nothingness. And one tightened fist at a time, we pull from it any material we can. Scoop by scoop, it slowly takes shape. And the more of our creation we see, however nascent or crude, the quicker our pace; our designs multiply and ambitions soar until we&amp;#39;re racing, and our own bodies struggle to fly alongside our imaginations, and from a soup of nothing except ourselves, we build.&lt;/p&gt;

&lt;p&gt;We build skyscrapers and cathedrals. Rockets and subways. All like lightning from our minds, striking down through our fingertips. Not measured in years or months, but hours and days. What was once impossible is now quaint, and what is inconceivable today will soon be common. That&amp;#39;s why we keep chasing and breathlessly rushing on to the next one.&lt;/p&gt;

&lt;p&gt;But for a small moment, we stand toes in the sand and hesitate, looking back at what we built before. A lucky few of our structures might still be illuminated in the night, faint beacons of our past success. But no, so much of it erodes...standing empty and forgotten. So much thought, so much effort, so much love and care left derelict and crumbling. It makes you wonder why we should even push onward.&lt;/p&gt;

&lt;p&gt;Because if you stop for too long, you can hear the echoes. Of the arguments and turmoil that went into constructing each one. Of what, and who, we lost along the way. And what it all used to mean to us, how exciting it was at the start. And really, that&amp;#39;s what&amp;#39;ll take it out of you: that it was actually &lt;em&gt;us&lt;/em&gt; that didn&amp;#39;t work out. That we rose too high, dallied too long, or even just chose the wrong thing to make. That it was our fault.&lt;/p&gt;

&lt;p&gt;And for that moment, it&amp;#39;s absolutely crippling. But, right before we succumb and fade away, we remember all those who came before us. No different than you and me, they hit the same walls, saw the same wreckage, and felt just as frozen. They too were ready to abandon it all, but instead they changed. They broke loose, and chose to live with and learn from their mistakes. It never got easier nor did it ever feel quite the same, but when it finally did work out...it was just electric.&lt;/p&gt;

&lt;p&gt;So we remember our past and advance cautiously, one step at a time. Until suddenly, seduced by the next hot spark of inspiration, we run. And we hope that what we build this time might be different.&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     <entry>
       <title>Billboards Are Like Facebook</title>
       <link href="http://clayallsopp.com/posts/billboards-are-like-facebook"/>
       <updated>2012-11-10T00:00:00-08:00</updated>
       <id>http://clayallsopp.com/posts/billboards-are-like-facebook</id>
       <content type="html">&lt;h1 id=&quot;toc_9224&quot;&gt;Billboards Are Like Facebook&lt;/h1&gt;

&lt;p&gt;Just a little over a month ago, Facebook started pushing its &amp;quot;*X* Is Like Facebook&amp;quot; campaign. It started with the infamous &lt;a href=&quot;http://www.youtube.com/watch?v=c7SjvLceXgU&quot;&gt;Chairs video&lt;/a&gt;, and they&amp;#39;ve kept it up with some other &lt;a href=&quot;https://www.facebook.com/photo.php?fbid=10151538653016729&amp;amp;set=a.376995711728.190761.20531316728&amp;amp;type=1&quot;&gt;extended metaphors&lt;/a&gt;. Say what you want about the campaign&amp;#39;s execution, but it&amp;#39;s to trying something seemingly off-beat and bold in its messaging. Really, what other company has tried to explicitly associate its product with solving existential loneliness?&lt;/p&gt;

&lt;p&gt;This is Facebook&amp;#39;s &lt;a href=&quot;https://www.facebook.com/facebook/info&quot;&gt;self-description&lt;/a&gt;: &amp;quot;Facebook&amp;#39;s mission is to give people the power to share and make the world more open and connected.&amp;quot;&lt;/p&gt;

&lt;p&gt;Many folks at Facebook, from top to bottom, believe that on a deep level. It&amp;#39;s an admirable mission. But to operate, Facebook also needs to be a company. This gives it a strange identity crisis; even Zuck&amp;#39;s &lt;a href=&quot;http://www.wired.com/business/2012/02/zuck-letter/&quot;&gt;letter to investors&lt;/a&gt; begins, &amp;quot;Facebook was not originally created to be a company.&amp;quot;&lt;/p&gt;

&lt;p&gt;This is my Newsfeed earlier today, colored red for ads and blue for non-ads. If you break red versus blue down into percentages, it&amp;#39;s 80% ads; if you want to count the navigation bar and side-navigation, then 54% advertising.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/QC4UE.png&quot; alt=&quot;newsfeed&quot;&gt;&lt;/p&gt;

&lt;p&gt;Examinations of Google like this have been &lt;a href=&quot;http://news.ycombinator.com/item?id=4476508&quot;&gt;done and discussed&lt;/a&gt; exhaustively. The takeaway from this isn&amp;#39;t &amp;quot;Facebook is 80% ads.&amp;quot; Instead, it just shows how much Facebook paid promotional content has above-the-fold.&lt;/p&gt;

&lt;p&gt;On one level, this does help me &amp;quot;connect&amp;quot; because the ads are almost always tied to one of my friends. My buddy Dylan likes Revolights; that could be insightful to me, so their sponsored story appears in my feed.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m not saying this is a bad way of advertising. Anecdotally, I have probably clicked or liked more things through Facebook&amp;#39;s promoted posts than Google searches. And I think user-promoted posts are a great way for people to surface content that they care a lot about.&lt;/p&gt;

&lt;p&gt;But really, advertising at all on Facebook leaves a funky taste in my mouth.&lt;/p&gt;

&lt;p&gt;Facebook is ostensibly about making the world &amp;quot;more open and connected,&amp;quot; but half the time I visit the site it&amp;#39;s dominated by paid promotions. And I get it, the company needs to make money, there&amp;#39;s nothing wrong with that in-and-of-itself.&lt;/p&gt;

&lt;p&gt;But then Facebook creates a video about how, &amp;quot;[The universe] is vast, and dark, and makes us wonder if we are alone.&amp;quot; That&amp;#39;s a powerful statement about existence, and it comes from a tech company. But it is a company nonetheless, and at the end of the day we&amp;#39;re being sold something.&lt;/p&gt;

&lt;p&gt;What bothers me is how we&amp;#39;re okay with this; that the tragedy of the video is the comical absurdity of the &amp;quot;Chair&amp;quot; analogy and not the deeper tragedy that any company is trying to connect with us like this at all. How one minute we&amp;#39;re being pitched about Facebook addressing the human condition, and the next we&amp;#39;re advertised to about Farmville. It&amp;#39;s a schizophrenic experience straight out of &lt;em&gt;Infinite Jest&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And you know what else? There&amp;#39;s this meta-cognitive dissonance where I know all of this, but right after I finish writing I&amp;#39;m actually going to go post about it on Facebook. And if you feel like participating in the absurdity, there&amp;#39;s also a Like button at the bottom of the page.&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     
 
     
     <entry>
       <title>☆ Give A Damn</title>
       <link href="http://clayallsopp.com/posts/give-a-damn"/>
       <updated>2012-10-27T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/give-a-damn</id>
       <content type="html">&lt;h1 id=&quot;toc_9217&quot;&gt;☆ Give A Damn&lt;/h1&gt;

&lt;p&gt;I want to tell you about The Kid. I met The Kid a few years ago, right out of high school. He had shipped some popular iPhone apps, made a few websites, had a bright future.&lt;/p&gt;

&lt;p&gt;I don&amp;#39;t know how it started, but The Kid really believed in &amp;quot;Move Fast and Break Things&amp;quot;. Ship-First-Questions-Later sort of guy. It made sense to him: the product was the purpose, and the code was a means to an end. He loved the things he could build, but wasn&amp;#39;t big on the process.&lt;/p&gt;

&lt;p&gt;So The Kid carried on and built a lot of cool stuff. I saw some of the code, and it ain&amp;#39;t pretty. But the end result still worked fine. And it got him pretty far, too. He&amp;#39;d flaunt these creations and eyes would go wide. It all looked impressive. He was young, sure, but who wouldn&amp;#39;t want to grab that talent while it was cheap?&lt;/p&gt;

&lt;p&gt;The Kid started working. He was famous for shipping new features that the users loved. And damn could he do it fast! Usually from idea to production in just a few days. Hundreds of lines of code in an afternoon, I kid you not. Lots of pats on his back, I&amp;#39;m sure. It all seemed to be working out for him, living the good life.&lt;/p&gt;

&lt;p&gt;And then things changed. I saw The Kid just about a year ago, working feverishly on a complete product redesign. Lots of new code, not a lot of time to think about it. Just him on the project, no second opinions or supervision. As with all redesigns, feature requests piled up at the pace of a bad game of Tetris. But who was The Kid to say no? Sleepless nights later, The Kid emerged with something. At first glance it looked great;  even I couldn&amp;#39;t believe it came together so quickly. Champion effort on his part, right?&lt;/p&gt;

&lt;p&gt;But here&amp;#39;s the rub: delve beneath the surface and it was just too buggy. And these weren&amp;#39;t just sloppy edge-case bugs, they were &amp;quot;What idiot do we need to fire?&amp;quot;-class problems. The redesign was shelved and rewritten again without The Kid.&lt;/p&gt;

&lt;p&gt;The Kid didn&amp;#39;t lose his job, but I could tell it hurt him like hell. Because to programmers like us, what is our work but extensions of ourselves? What did this disaster say about The Kid?&lt;/p&gt;

&lt;p&gt;He laid low for a bit, ashamed of what he had done. Moving fast and breaking things had gotten him far, but now he had finally broken too much. Kind of world-shattering to him, I guess. It was a dark place for The Kid.&lt;/p&gt;

&lt;p&gt;And that&amp;#39;s when I heard The Kid grew up. You could say he became The Guy, The Dude, whatever; the point is he had a change of heart. He started to realize shipping might not be everything. His screwup was a loud wakeup call that he needed to change his scene.&lt;/p&gt;

&lt;p&gt;And so (and this is all hearsay, mind you) The Kid started caring about his code. Not just caring, but really giving a damn about it. And not because it was a means to an end, but for the sole sake of caring about it. &amp;quot;Code is more than just a tool,&amp;quot; I heard he said. &amp;quot;It&amp;#39;s our craft. It&amp;#39;s our muscle. And we need to train it. Chop wood. Carry water. Code.&amp;quot;&lt;/p&gt;

&lt;p&gt;I heard all sorts of wild rumors. That The Kid started using &amp;quot;best practices&amp;quot; in all his Google searches. That he started learning the deep internals of the beasts he wrangled, whether it were Rails or iOS or whatever, just for the intellectual pleasure of it all. Code was no longer a beast to be tamed; it was a creature, to be both studied and admired. He even tried to teach others the error of his old ways. Wild stuff, right?&lt;/p&gt;

&lt;p&gt;Did The Kid completely abandon his old ways? Well, apparently not. He said something about how there&amp;#39;s a, &amp;quot;time and place for everything.&amp;quot; That sometimes we need to ship fast and will break things. But if we take all the other time we have and put it to good use by really learning and crafting our code, we&amp;#39;ll break less.&lt;/p&gt;

&lt;p&gt;Kind of a crazy change, but I&amp;#39;d believe it. I thought a lot of things about The Kid when I met him a years ago, but I didn&amp;#39;t think he was stupid. He grew and evolved as we all do. And he&amp;#39;s probably not even done yet, wherever he is. But next time you need to move fast, take a deep breath before taking the dive. Remember The Kid in all of us.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Don't Say Startup</title>
       <link href="http://clayallsopp.com/posts/dont-say-startup"/>
       <updated>2012-10-09T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/dont-say-startup</id>
       <content type="html">&lt;h1 id=&quot;toc_9216&quot;&gt;Don&amp;#39;t Say Startup&lt;/h1&gt;

&lt;p&gt;The word &amp;quot;startup&amp;quot; gets thrown around a lot. Mainstream media calls Twitter and any other pre-IPO company a startup, PG says startups are businesses that &lt;a href=&quot;http://paulgraham.com/growth.html&quot;&gt;grow fast&lt;/a&gt;, and Peter Thiel says startups are all about &lt;a href=&quot;http://blakemasters.tumblr.com/post/21169325300/peter-thiels-cs183-startup-class-4-notes-essay&quot;&gt;unique business models&lt;/a&gt;. That all sounds pretty reasonable, right?&lt;/p&gt;

&lt;p&gt;But at any given Silicon Valley event, you have some folks referring to all variety of what they&amp;#39;re working on as &amp;quot;startups&amp;quot;. It could be their one-man iPhone app, a newborn hackathon project, or even the legendary stealth-mode project. I know I&amp;#39;m guilty of it too.&lt;/p&gt;

&lt;p&gt;So I&amp;#39;ve made a new rule: unless you&amp;#39;ve raised money, are bringing in substantial revenue, or have a sizable active user base, don&amp;#39;t call whatever you&amp;#39;re building a startup. I&amp;#39;m not trying to belittle or be a jerk; I&amp;#39;m hoping to cut everyone some slack.&lt;/p&gt;

&lt;p&gt;Every time you introduce your product to someone as a startup, you set an expectation for where the conversation is going next: your funding, revenue, user base, that sort of talk. That might be appropriate, but if you&amp;#39;re not at that stage where it&amp;#39;s a proper startup then you&amp;#39;ll inevitably fail to meet those expectations. And that sucks, because you lose a little social capital each time that happens.&lt;/p&gt;

&lt;p&gt;You&amp;#39;ve probably been on the other side of this conversation: someone tells you they&amp;#39;re doing a startup, you ask for details, and it turns out to be pretty nascent. Kind of a let down, right? It probably would have ended better if they had avoided the word &amp;quot;startup&amp;quot;.&lt;/p&gt;

&lt;p&gt;Instead, focus on &lt;em&gt;what&lt;/em&gt; you&amp;#39;re building and resist putting a label on it. Say something like, &amp;quot;We&amp;#39;re building &lt;em&gt;x&lt;/em&gt;&amp;quot; or &amp;quot;We just launched our product, &lt;em&gt;y&lt;/em&gt;.&amp;quot; This should make sense: your product is what people care about, whether or not your venture really is a startup. Or if you&amp;#39;re not quite ready to reveal what you&amp;#39;re doing, then a simple &amp;quot;I&amp;#39;m working on my own thing right now,&amp;quot; is satisfactory.&lt;/p&gt;

&lt;p&gt;The more we throw around the word &amp;quot;startup&amp;quot;, the less of an impact it has when we actually want it to matter. So do yourself and the community a favor: drop it only once you mean it.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>RubyMotion Metaprogramming</title>
       <link href="http://clayallsopp.com/posts/rubymotion-metaprogramming"/>
       <updated>2012-09-23T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/rubymotion-metaprogramming</id>
       <content type="html">&lt;h1 id=&quot;toc_9204&quot;&gt;RubyMotion Metaprogramming&lt;/h1&gt;

&lt;p&gt;Metaprogramming is pretty neat. While there is an awfully fun mad-scientist feeling I get when my code creates and redefines methods and entire classes at runtime, metaprogramming is not for every programmer or every project. But when it &lt;em&gt;is&lt;/em&gt; able to make your life easier, I&amp;#39;m very thankful it can be wrangled Ruby.&lt;/p&gt;

&lt;p&gt;Now, conventional Ruby&amp;#39;s flexibility and really-everything-can-change-at-runtime mentality come at a high cost with respect to performance; thankfully, RubyMotion isn&amp;#39;t your father&amp;#39;s Ruby. Its language is a compiled variant of Ruby that implements most of the standard library but without all of the slow interpreted cruft. Basically, this means we can&amp;#39;t use &lt;code&gt;eval&lt;/code&gt;, but RubyMotion still supports most of desktop Ruby&amp;#39;s metaprogramming functions (we&amp;#39;ll get to specifics soon, I promise).&lt;/p&gt;

&lt;p&gt;Is it a huge deal to have this ability on iOS? The short answer is yes, assuming it floats your boat. Despite being built on top of good-ole C, Objective-C actually has some neat metaprogramming functionality tucked away in &lt;code&gt;objc/runtime.h&lt;/code&gt;; however, it&amp;#39;s not a first-class part of the language and isn&amp;#39;t a go-to tool like the Ruby community has made &lt;code&gt;method_missing&lt;/code&gt; or &lt;code&gt;define_method&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So if you&amp;#39;ve always wanted more &amp;quot;meta&amp;quot; in your iOS code, let&amp;#39;s jump into what RubyMotion does and does not support (hint: it supports everything important). In the meantime, I&amp;#39;ll try to keep it real and give examples from actual code that I&amp;#39;ve written.&lt;/p&gt;

&lt;h6 id=&quot;toc_9205&quot;&gt;&lt;code&gt;send&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;I don&amp;#39;t know if you can count this as proper metaprogramming, but it does reveal one of the fundamentals of Ruby: methods can be invoked dynamically using just strings. Why is that a big deal? We can take a lot of &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elsif&lt;/code&gt; code and use &lt;code&gt;send&lt;/code&gt; to simplify it into one call like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tableView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tableView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;didSelectRowAtIndexPath&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:indexPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;menu_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;menu_items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indexPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;#39;profile&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;open_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;menu_row&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#...; end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open_messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#...; end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open_feed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# ...; end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now when we add more rows to &lt;code&gt;self.menu_items&lt;/code&gt;, we don&amp;#39;t have to mess with &lt;code&gt;didSelectRowAtIndexPath:&lt;/code&gt; at all! It scales with the rest of our product. Neat, right?&lt;/p&gt;

&lt;h6 id=&quot;toc_9206&quot;&gt;&lt;code&gt;define_method&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;Since we can invoke methods dynamically, wouldn&amp;#39;t it be nice if we could add them just the same? Well, you&amp;#39;re in luck because &lt;code&gt;define_method&lt;/code&gt; was &lt;a href=&quot;http://blog.rubymotion.com/post/31917526853/rubymotion-gets-ios-6-iphone-5-debugger&quot;&gt;just&lt;/a&gt; added to RubyMotion. With it, we can define (or re-define) a methods using a string and a block.&lt;/p&gt;

&lt;p&gt;We can write part of the canonical &lt;code&gt;has_one&lt;/code&gt; method from ActiveRecord in RubyMotion like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Profile&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# EX: has_one :user&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;has_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make_klass_from_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# EX: =&amp;gt; User&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Effect: (a_profile.user) === User.first(conditions: &amp;quot;profile_id = 4&amp;quot;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_id = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Effect: (a_profile.user = a_user) === a_user.profile_id = 4&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_id=&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;profile&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Make sense? One confusing part might be that &lt;code&gt;define_method&lt;/code&gt; appears to jump around in scope: when we define &lt;code&gt;#{name}&lt;/code&gt;, our definition uses both the local &lt;code&gt;klass&lt;/code&gt; variable from &lt;code&gt;has_one&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; a reference to &lt;code&gt;self.class&lt;/code&gt;. This is because &lt;code&gt;define_method&lt;/code&gt; uses a normal Ruby block for its method definition, and thus is a proper &lt;a href=&quot;http://stackoverflow.com/questions/2029524/how-are-variables-bound-to-the-body-of-a-define-method&quot;&gt;closure&lt;/a&gt;. In less fancy words, it&amp;#39;ll snatch local variables assigned outside of &lt;code&gt;define_method&lt;/code&gt; and keep a reference to them in the definition for when the new function is actually called; everything else is evaluated in the scope of an instance of our &lt;code&gt;Profile&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Using generic variables like &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;klass&lt;/code&gt; can make things hard to grok, so use &lt;code&gt;define_method&lt;/code&gt; with caution. It can be incredibly powerful and speed up repetitive tasks, but can also make things a headache to debug.&lt;/p&gt;

&lt;p&gt;You might have noticed we used a parameter in our block for &lt;code&gt;#{name}=&lt;/code&gt;, which tells the definition that our function takes one argument. You might find a circumstance where you want to play with default values or pass a &lt;code&gt;&amp;amp;block&lt;/code&gt; to a dynamically added method; for those, the normal &lt;code&gt;do&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt; blocks will not suffice. Instead, use the stubby-lambda syntax, which allows every convention of a normal function definition:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Stubby lambda: -&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_with_default&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:my_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;arg1 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; args &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9207&quot;&gt;&lt;code&gt;define_singleton_method&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;Sometimes you want to add a method to a class, not an instance. For this, we use &lt;code&gt;define_singleton_method&lt;/code&gt;, which functions just like &lt;code&gt;define_method&lt;/code&gt; except acting on the &lt;em&gt;class&lt;/em&gt; in question:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sayer&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shouts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;define_singleton_method&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shout_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upcase&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;shouts&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:goodbye&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Sayer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shout_hello&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HELLO&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Sayer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shout_goodbye&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GOODBYE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;For a more practical example, you might check out &lt;a href=&quot;https://gist.github.com/875697&quot;&gt;this gist&lt;/a&gt; by &lt;a href=&quot;http://senthilnambi.posterous.com/definemethod-vs-definesingletonmethod&quot;&gt;@senthilnambi&lt;/a&gt;.&lt;/p&gt;

&lt;h6 id=&quot;toc_9208&quot;&gt;&lt;code&gt;alias_method&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;Pretty nifty method to copy current method definitions into a differently named function. Sometimes you do this to just change the function name, but other times you can use it to preserve an existing implementation and make use of it later. &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UIView&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;alias_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:background_color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:backgroundColor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9209&quot;&gt;&lt;code&gt;instance_eval&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;instance_eval&lt;/code&gt; shipped with the original version of RubyMotion and is particularly useful in the creation of DSLs. Any block you pass to it will be evaluated in the context of the object it is invoked on. Lots of big words in there, so check this out:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;table_cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;special_subview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# alias_method is private, so have to use #send&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;table_cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:alias_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:old_layoutSubviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:layoutSubviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;table_cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;layoutSubviews&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# nifty trick, right?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;old_layoutSubviews&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_special_subview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewWithTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SPECIAL_SUBVIEW_TAG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_special_subview&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Normally, if we wanted to add custom behavior in &lt;code&gt;layoutSubviews&lt;/code&gt; we&amp;#39;d have to create a custom subclass. This might be appropriate, but in &lt;a href=&quot;form&quot;&gt;Formotion&lt;/a&gt;&amp;#39;s case we often needed to apply changes to just &lt;a href=&quot;https://github.com/clayallsopp/formotion/blob/master/lib/formotion/row_type/slider_row.rb&quot;&gt;one instance&lt;/a&gt; of a view.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;instance_eval&lt;/code&gt; is especially powerful in creating DSLs. Usually DSLs will take a block supplied by the user and simply run &lt;code&gt;instance_eval&lt;/code&gt; on it, like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UIViewDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;instance_eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;background_color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Color&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithFrame&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CGRectZero&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;UIViewDSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;a_view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;background_color&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:black&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note that because our &lt;code&gt;&amp;amp;block&lt;/code&gt; in &lt;code&gt;create_view&lt;/code&gt; is passed around, &lt;code&gt;background_color&lt;/code&gt; and &lt;code&gt;frame&lt;/code&gt; are actually invoking methods of &lt;code&gt;UIViewDSL&lt;/code&gt;.&lt;/p&gt;

&lt;h6 id=&quot;toc_9210&quot;&gt;&lt;code&gt;class_eval&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;So if &lt;code&gt;instance_eval&lt;/code&gt; applies to an instance, how do we cascade changes to &lt;em&gt;all&lt;/em&gt; instances? We can use &lt;code&gt;class_eval&lt;/code&gt; on a &lt;code&gt;Class&lt;/code&gt; and apply the same technique:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;Fixnum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;random&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9211&quot;&gt;&lt;code&gt;module_eval&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;You get the idea.&lt;/p&gt;

&lt;h6 id=&quot;toc_9212&quot;&gt;&lt;code&gt;const_get&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;const_get&lt;/code&gt; is how we grab classes, modules, and constants at runtime. The object on which we invoke &lt;code&gt;const_get&lt;/code&gt; determines the scope of the results we get back; for example, grabbing a &lt;code&gt;User&lt;/code&gt; class from a &lt;code&gt;Facebook&lt;/code&gt; module versus a &lt;code&gt;Twitter&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;I use this often to wrap the LongPrefixedObjectiveCConstants as symbols:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# EX const_int_get(&amp;quot;UIReturnKey&amp;quot;, :done) =&amp;gt; UIReturnKeyDone == 9&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;const_int_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_a?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Numeric&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;camelize&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# from the BubbleWrap/Camera source:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# @options[:source_type] is like :photo_library or :camera&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;const_int_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;UIImagePickerControllerSourceType&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:source_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The one downside to using &lt;code&gt;const_get&lt;/code&gt; in RubyMotion is that all of the Objective-C integer constants &lt;em&gt;must&lt;/em&gt; exist in your source code to get added at compile-time. For a good example, check the source to &lt;a href=&quot;https://github.com/rubymotion/BubbleWrap/blob/master/motion/core/device/camera.rb#L202&quot;&gt;BubbleWrap&amp;#39;s Camera&lt;/a&gt; module.&lt;/p&gt;

&lt;h6 id=&quot;toc_9213&quot;&gt;&lt;code&gt;const_defined?&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;const_get&lt;/code&gt; will throw an error if we try to grab an undefined constant, so it might be a swell idea to run some type of safety check beforehand. &lt;code&gt;const_defined?&lt;/code&gt; lets us do just that:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_defined?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;UIView&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Kernel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_defined?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;UIAwesomeView&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9214&quot;&gt;&lt;code&gt;const_set&lt;/code&gt;&lt;/h6&gt;

&lt;p&gt;If we can get and check for constants, then all that&amp;#39;s left is to create them. Again, mind the scope at which you call this function; so far we&amp;#39;ve been using &lt;code&gt;Kernel&lt;/code&gt;, which is the top-level scope, but you could accidentally override existing constants or classes.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s say we wanted to create a new subclass at runtime. That sounds pretty crazy, but &lt;code&gt;call&lt;/code&gt; me maybe?&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;green&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;color_klass_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;UI&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;View&amp;quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; UIGreenView&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_defined?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color_klass_str&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color_klass_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color_klass_str&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ancestors&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; [UIGreenView, UIView, UIResponder, NSObject, Kernel]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;backgroundColor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Color&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# By default, our UIGreenViews will have green background colors.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And if you don&amp;#39;t get goosebumps doing that, I don&amp;#39;t know what thrills you.&lt;/p&gt;

&lt;h2 id=&quot;toc_9215&quot;&gt;What&amp;#39;s not supported?&lt;/h2&gt;

&lt;p&gt;To my knowledge, only the string-based &lt;code&gt;eval&lt;/code&gt; methods (which rely on an full-blown interpreter) and &lt;code&gt;Binding&lt;/code&gt;s are not available in RubyMotion. With the recent addition of &lt;code&gt;define_method&lt;/code&gt;, I&amp;#39;m &lt;a href=&quot;http://clayallsopp.com/posts/what-excites-me-about-rubymotion/&quot;&gt;even more&lt;/a&gt; excited to see what else comes out of the RubyMotion community.&lt;/p&gt;

&lt;p&gt;If you have any questions or qualms, continue the discussion on &lt;a href=&quot;http://news.ycombinator.com/item?id=4562281&quot;&gt;Hacker News&lt;/a&gt; or send me a &lt;a href=&quot;http://twitter.com/clayallsopp&quot;&gt;tweet&lt;/a&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>What Excites Me About RubyMotion</title>
       <link href="http://clayallsopp.com/posts/what-excites-me-about-rubymotion"/>
       <updated>2012-09-14T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/what-excites-me-about-rubymotion</id>
       <content type="html">&lt;h1 id=&quot;toc_9203&quot;&gt;What Excites Me About RubyMotion&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://rubymotion.com&quot;&gt;RubyMotion&lt;/a&gt; made a splash when it came out four months ago. But summer wanes and winter is coming, so where are we now? By far, the most exciting change has been the growth of the community and what it&amp;#39;s cooking.&lt;/p&gt;

&lt;p&gt;From my perspective, RubyMotion libraries have gone through three waves. The first are very thin shortcuts for the original Objective-C functions; mostly, these are to reduce keystrokes and add a bit of Ruby flair. They&amp;#39;re low-hanging fruit, and &lt;a href=&quot;http://github.com/rubymotion/bubblewrap&quot;&gt;BubbleWrap&lt;/a&gt; has them in spades:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# NSSearchPathForDirectoriesInDomains...&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;documents_path&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# NSBundle.mainBundle.resourcePath&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resources_path&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# NSNotificationCenter.defaultCenter&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;notification_center&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;These are nifty, but not a huge win over Objective-C; we get a little more unique with the second wave of new libraries. These abstract entire classes and frameworks into idiomatic Ruby wrappers. A lot of the vestigial Objective-C paradigms (delegation, protocols, selectors) don&amp;#39;t make sense in Ruby and having a layer of abstraction hiding these details is a step in the right direction. For example, check out how BubbleWrap handles using the front-facing camera:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;BW&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;camera&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;front&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;picture&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:original_image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Clean, right? No dealing with &lt;code&gt;UIImagePickerController&lt;/code&gt; or its protocol. &lt;a href=&quot;http://github.com/clayallsopp/twittermotion&quot;&gt;Twittermotion&lt;/a&gt; uses a similar structure for composing a tweet with the iOS native interface:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;Twitter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Composer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello RubyMotion!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://clayallsopp.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;composer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;composer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cancelled?&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# user didnt sent the tweet&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;composer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;done?&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# user sent the tweet&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Most of these wrappers are probably implementable in Objective-C, but they are tremendously easier to grok at-a-glance for Rubyists and any others just beginning iOS development.&lt;/p&gt;

&lt;p&gt;At this point, it would be understandable if you still didn&amp;#39;t think RubyMotion merited its $200 price tag. But before you close the tab and move on, there&amp;#39;s one more wave of RubyMotion libraries: those that invent completely &lt;em&gt;new metaphors&lt;/em&gt; for development.&lt;/p&gt;

&lt;p&gt;What do I mean by new metaphors? These libraries do more than just wrap the standard iOS SDK: they turn it on its head and allow us to express ourselves in novel ways. Take &lt;a href=&quot;http://github.com/rubymotion/teacup&quot;&gt;Teacup&lt;/a&gt;, which lets us separate our layout and style logic into &lt;code&gt;Stylesheet&lt;/code&gt; objects:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;Teacup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Stylesheet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:menu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;landscape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:menu_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;landscape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;240&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# make it wide in landscape view&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Menu&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MenuController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIViewController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;stylesheet&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:menu&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@menu_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:menu_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Instead of spending dozens of lines doing frame calculations and positions in our controllers, we can separate these parameters into a smarter object. Given how thick iOS controllers can become if unmanaged, it&amp;#39;s a major boon for when you need programmatic control of your views. Plus, since &lt;code&gt;Stylesheet&lt;/code&gt;s are normal Ruby objects, perhaps we could dynamically create them from a server configuration or let the user tweak them to as preferred.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://clayallsopp.github.com/formotion&quot;&gt;Formotion&lt;/a&gt; is another &amp;quot;new metaphor&amp;quot; library; it allows you to declaratively construct complex and interactive views. Although you can create standalone form-based layouts like the Settings and Contacts apps, views can also be constructed using just a model&amp;#39;s definition. This lets us prototype screens in an application&amp;#39;s flow incredibly quickly, like this little example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Formotion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Formable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;form_property&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;form_property&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;form_property&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:team&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Red&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Blue&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Green&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;form_title&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Edit User&amp;quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Harry&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Green&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Formotion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FormableController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/hm3nQ.png&quot; alt=&quot;Formotion&quot;&gt;&lt;/p&gt;

&lt;p&gt;Pretty incredible that I can construct a non-trivial UI with only what, a dozen lines of code?&lt;/p&gt;

&lt;p&gt;And these libraries are just the start of a wholly new way of looking at how we structure and develop mobile apps. This is why I keep pushing myself to create with RubyMotion, as to re-think the status quo of the past five years. iOS development has come a long way since 2008 and there&amp;#39;s absolutely nothing wrong about the current APIs, but Ruby seems to help developers frame tasks in new a new and often revealing light.&lt;/p&gt;

&lt;p&gt;So is it worth the price tag? For some, still maybe not quite yet. But what just the past few months have shown is a window into something fresh. And to me, that&amp;#39;s just plain &lt;em&gt;exciting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was adapted from a &lt;a href=&quot;http://www.slideshare.net/clayallsopp/the-future-of-rubymotion&quot;&gt;talk&lt;/a&gt; I gave at an &lt;a href=&quot;http://www.meetup.com/SF-Bay-RubyMotion&quot;&gt;SF Bay RubyMotion Meetup&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     <entry>
       <title>It's Just X Through Y While Z</title>
       <link href="http://clayallsopp.com/posts/just-x-through-y-while-z"/>
       <updated>2012-08-27T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/just-x-through-y-while-z</id>
       <content type="html">&lt;h1 id=&quot;toc_9201&quot;&gt;It&amp;#39;s &lt;em&gt;Just&lt;/em&gt; X Through Y While Z&lt;/h1&gt;

&lt;p&gt;Every few days, I&amp;#39;ll see an idea dismissed on Hacker News because of its simplicity. Typically, engineers see some new product and state that it&amp;#39;s &lt;em&gt;just&lt;/em&gt; some chain of obvious technical steps.&lt;/p&gt;

&lt;p&gt;For example, Dropbox &lt;a href=&quot;http://news.ycombinator.com/item?id=9224&quot;&gt;was &lt;em&gt;just&lt;/em&gt;&lt;/a&gt; &amp;quot;an FTP account, [mounted] locally with curlftpfs, [using] SVN or CVS on the mounted filesystem.&amp;quot; Heroku was &lt;em&gt;just&lt;/em&gt; git hosted on AWS with a post-commit hook to boot a Rails server. Square was &lt;em&gt;just&lt;/em&gt; a magnetic reader using the headphone jack. Easy stuff, right?&lt;/p&gt;

&lt;p&gt;In fact, almost every successful product which can be reduced &amp;quot;basic&amp;quot; steps. Perhaps there are so few counter-examples &lt;em&gt;because&lt;/em&gt; products with irreducible innovations are rarely executed as well as their seemingly straightforward counterparts. It&amp;#39;s hard to simultaneously come up with raw, astounding technology and still ship a great customer experience. Usually it is only the next generation of companies that can take the technology and execute on a succcessful product.&lt;/p&gt;

&lt;p&gt;The famous example is &lt;a href=&quot;http://en.wikipedia.org/wiki/Xerox_PARC#Accomplishments&quot;&gt;Xerox PARC&lt;/a&gt;: even though the Alto and the Star featured groundbreaking innovations, it would be years until Apple and others successfully brought PARC&amp;#39;s research to the masses. This is why I&amp;#39;m skeptical of Google&amp;#39;s ability to successfully commercialize its self-driving car; instead, I&amp;#39;d bet on a future entity that takes Google&amp;#39;s work and makes incremental but key improvements. Of course, such an effort will inevitably be dismissed as, &amp;quot;just Google&amp;#39;s tech but with &lt;em&gt;x&lt;/em&gt;.&amp;quot;&lt;/p&gt;

&lt;p&gt;It&amp;#39;s peculiar that we are so eager to dismiss ideas in this way, and yet it&amp;#39;s apparently difficult to do the inverse. Out of habit or hubris, we miss the unconscious steps we take everyday to solve our technological pains. And when we do notice some minor repititions in our work, we resort to equally small engineering improvements like scripts and increased automation.&lt;/p&gt;

&lt;p&gt;Such solutions are great and vital to building a product, but we fail to see the macro-problems that really hinder our progress: &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;CRUD development&lt;/a&gt; sucks, &lt;a href=&quot;http://pusher.com/&quot;&gt;real-time&lt;/a&gt; sucks, &lt;a href=&quot;http://stripe.com&quot;&gt;payments&lt;/a&gt; suck, the list of problems we&amp;#39;ve already realized goes on and on. They sound obvious now, but such problems exist for years before someone stumbles upon the Better Way. What else belongs on this list hiding right under our noses?&lt;/p&gt;

&lt;p&gt;Just the other day, I read about how watching Netflix abroad isn&amp;#39;t &amp;quot;&lt;a href=&quot;http://news.ycombinator.com/item?id=4416155&quot;&gt;terribly difficult&lt;/a&gt;.&amp;quot; Next time you see that sort of list, it wouldn&amp;#39;t be a bad idea to take note of the opportunity before you. And better yet, you should give pause and wonder if there&amp;#39;s a greater problem afoot than &lt;em&gt;just&lt;/em&gt; taking &lt;em&gt;x&lt;/em&gt; and going through &lt;em&gt;y&lt;/em&gt; while &lt;em&gt;z&lt;/em&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Mixing Objective-C and Ruby</title>
       <link href="http://clayallsopp.com/posts/mixing-objective-c-and-ruby"/>
       <updated>2012-08-24T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/mixing-objective-c-and-ruby</id>
       <content type="html">&lt;h1 id=&quot;toc_9197&quot;&gt;Mixing Objective-C and Ruby&lt;/h1&gt;

&lt;p&gt;I&amp;#39;ve &lt;a href=&quot;/posts/the-ruby-motion-way/&quot;&gt;written&lt;/a&gt; a &lt;a href=&quot;http://rubymotion-tutorial.com&quot;&gt;lot about&lt;/a&gt; RubyMotion, but one aspect I haven&amp;#39;t touched on is how you can mix-and-match Objective-C and Ruby. That means you can use Objective-C code in RubyMotion projects &lt;em&gt;and&lt;/em&gt; use Ruby code in traditional Objective-C apps. That sounds like black-magic, so let&amp;#39;s walk through some quick examples.&lt;/p&gt;

&lt;h2 id=&quot;toc_9198&quot;&gt;Objective-C in Ruby&lt;/h2&gt;

&lt;p&gt;Most iOS developers have a deep backlog of existing code, and porting it to RubyMotion by hand is a pain. Luckily, we can just add the compiled Objective-C to our shiny new RubyMotion apps.&lt;/p&gt;

&lt;p&gt;Imagine we have a &lt;code&gt;CYAlert&lt;/code&gt; class we want to use in our RubyMotion app; it&amp;#39;s pretty short and looks something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;cp&quot;&gt;// CYAlert.h&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CYAlert&lt;/span&gt; : &lt;span class=&quot;nc&quot;&gt;NSObject&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;cp&quot;&gt;// CYAlert.m&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#import &amp;quot;CYAlert.h&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CYAlert&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UIAlertView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIAlertView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&amp;quot;This is Objective-C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&amp;quot;Mixing and matching!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;addButtonWithTitle:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&amp;quot;OK&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To use this in our RubyMotion app, we just put both files inside a folder (such as &lt;code&gt;./vendor/CYAlert&lt;/code&gt;) and tell RubyMotion to also build that folder using &lt;code&gt;vendor_project&lt;/code&gt; in the &lt;code&gt;Rakefile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;no&quot;&gt;Motion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Use `rake config&amp;#39; to see complete project settings.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;MixingExample&amp;#39;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ./vendor/CYAlert contains CYAlert.h and CYAlert.m&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vendor_project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;vendor/CYAlert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now in our &lt;code&gt;AppDelegate&lt;/code&gt;, we can use our &lt;code&gt;CYAlert&lt;/code&gt; as expected:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AppDelegate&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;didFinishLaunchingWithOptions&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:launchOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CYAlert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Pretty neat, huh? RubyMotion knows how to build two types of Objective-C codebases: &lt;code&gt;:static&lt;/code&gt; as shown above and &lt;code&gt;:xcode&lt;/code&gt;, which is exactly what it sounds like. You can read more about the options for both in the &lt;a href=&quot;http://www.rubymotion.com/developer-center/guides/project-management/#_using_3rd_party_libraries&quot;&gt;RubyMotion docs&lt;/a&gt;.&lt;/p&gt;

&lt;h6 id=&quot;toc_9199&quot;&gt;CocoaPods&lt;/h6&gt;

&lt;p&gt;Since RubyMotion can build any old Xcode project, using the existing &lt;a href=&quot;http://cocoapods.org/&quot;&gt;CocoaPods&lt;/a&gt; system doesn&amp;#39;t require a huge leap of imagination. The &lt;a href=&quot;https://github.com/HipByte/motion-cocoapods&quot;&gt;motion-cocoapods&lt;/a&gt; gem adds a nice DSL to automate the process in your &lt;code&gt;Rakefile&lt;/code&gt;, like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;motion-cocoapods&amp;#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Motion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pod&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;JSONKit&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;toc_9200&quot;&gt;Ruby in Objective-C&lt;/h2&gt;

&lt;p&gt;Compiling to a common bytecode is a two-way street: we can also bundle Ruby classes into Objective-C projects. &lt;em&gt;That&lt;/em&gt; sounds wild, right? Imagine we re-implemented our &lt;code&gt;CYAlert&lt;/code&gt; in Ruby, like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# ./app/CYAlert.rb&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CYAlert&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIAlertView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;This is Ruby&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Mixing and matching!&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addButtonWithTitle&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;OK&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If we run &lt;code&gt;rake static&lt;/code&gt;, this will compile our project into a static library at &lt;code&gt;./build/&amp;lt;app name&amp;gt;-universal.a&lt;/code&gt;. We then add this to our Xcode project with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add static library to project
&lt;img src=&quot;http://i.imgur.com/84Zkr.png&quot; alt=&quot;in library&quot;&gt;&lt;/li&gt;
&lt;li&gt;Link against additional required libraries
&lt;img src=&quot;http://i.imgur.com/187Qq.png&quot; alt=&quot;linker&quot;&gt;&lt;/li&gt;
&lt;li&gt;Initalize the RubyMotion runtime&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;c syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// main.m&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoreleasepool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RubyMotionInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;RubyMotionInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now we&amp;#39;re cooking with gas. One caveat: RubyMotion does not generate &lt;code&gt;.h&lt;/code&gt; files for us, so we have to manually declare our classes and methods somewhere in Objective-C. It&amp;#39;s a good idea to create a header for each class, so we could create a &lt;code&gt;CYAlert.h&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// CYAlert.h&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CYAlert&lt;/span&gt; : &lt;span class=&quot;nc&quot;&gt;NSObject&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CYAlert&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Empty on purpose&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And in any of our classes, such as the app delegate, we need only import the header and use to our heart&amp;#39;s content:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;cp&quot;&gt;// ExampleDelegate.m&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#import &amp;quot;CYAlert.h&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;BOOL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIApplication&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;didFinishLaunchingWithOptions:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSDictionary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;launchOptions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CYAlert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;YES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So if something is painful to write in Objective-C, just write it in Ruby and easily add it to your project. &lt;em&gt;Super&lt;/em&gt; neat stuff.&lt;/p&gt;

&lt;p&gt;You can find the source for the above examples &lt;a href=&quot;https://github.com/clayallsopp/mixing-objc-ruby&quot;&gt;on Github&lt;/a&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     
 
     
     <entry>
       <title>That Makes Us Look Really Bad.</title>
       <link href="http://clayallsopp.com/posts/square-that-makes-us-look-really-bad"/>
       <updated>2012-08-08T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/square-that-makes-us-look-really-bad</id>
       <content type="html">&lt;h1 id=&quot;toc_9195&quot;&gt;&amp;ldquo;That makes us look really bad.&amp;rdquo;&lt;/h1&gt;

&lt;p&gt;Square&amp;#39;s office is enveloped by wall-mounted monitors. I&amp;#39;m sure they usually display some interesting charts, but they&amp;#39;re automatically blacked-out the moment a guest like me arrives. In typical Square fashion, they&amp;#39;re not merely turned off: they display an elegant black Square logo on a dark textured background.&lt;/p&gt;

&lt;p&gt;However, there was one near the entrance still displaying &lt;a href=&quot;https://twitter.com/about/resources/widgets/widget_search&quot;&gt;Twitter&amp;#39;s Feed widget&lt;/a&gt; with tweets about @Square. Stretched across the screen, ceaseless praise about their products scrolled by in an interface not too dissimilar to this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/0VKMn.png&quot; alt=&quot;Square tweets&quot;&gt;&lt;/p&gt;

&lt;p&gt;I was speaking to some folks nearby, when someone looked up to the monitor and rendered that squinting expression when you first notice a scratch on your car. He uttered: &amp;ldquo;Wow, that makes us look &lt;em&gt;really&lt;/em&gt; bad.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Everyone turned to the newfound blemish. He continued: &amp;ldquo;I&amp;#39;m going to fix that later tonight. Slap on Helvetica, increase the line height, maybe add some texture.&amp;rdquo; The others concurred with his assessment.&lt;/p&gt;

&lt;p&gt;I agreed it did need some work, but I was still focused on the first thing he said: &amp;ldquo;That makes &lt;em&gt;us&lt;/em&gt; look really bad&amp;rdquo;. He didn&amp;#39;t have any relation to the team who put that on the screen, but he knew the style clashed with Square&amp;#39;s crafted image of polish and perfection. He had nothing to gain from restyling the view, but still wanted go out of his way for the good of the company. Very few would ever see that monitor, and yet its imperfection put a dent in everything that Square had achieved.&lt;/p&gt;

&lt;p&gt;Maybe I&amp;#39;m making a big deal out of nothing, maybe that was just his thing. But from what I&amp;#39;ve seen from Square&amp;#39;s employees and its products, I think it runs deeper than that. It&amp;#39;s the kind of culture that makes amazing things happen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Square recently made two announcements: a partnership with Starbucks and a flat monthly fee for credit card charges.&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>The Problem With Kickstarter And Software</title>
       <link href="http://clayallsopp.com/posts/the-problem-with-kickstarter-and-software"/>
       <updated>2012-08-05T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/the-problem-with-kickstarter-and-software</id>
       <content type="html">&lt;h1 id=&quot;toc_9194&quot;&gt;The Problem With Kickstarter And Software&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: Hey Socrates, thanks for taking the time to grab coffee with me. We&amp;#39;re really excited about how our new software product is going to make customers&amp;#39; lives a lot better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: That sounds great, how far along are you?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: We&amp;#39;ve been hard working for the past three months and have a polished beta, but we&amp;#39;re not quite ready yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: Sounds like you should start drumming up interest for a launch. What&amp;#39;s your customer acquisition strategy?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: Well, we&amp;#39;re going to launch on Kickstarter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: Oh? The crowd-funding website?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: Yeah, we think it&amp;#39;ll be a great platform to get some early adopters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: But haven&amp;#39;t you already raised venture capital? Why do you need the additional Kickstarter funds to continue work?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: It&amp;#39;s not about the money, we obviously don&amp;#39;t need any more. But we do need paying customers, and Kickstarter can give us those in spades. It&amp;#39;s less competitive than the App Store, and definitely less crowded than the entire web, so it should get a lot of fresh eyeballs on the product. It was impossible &lt;em&gt;not&lt;/em&gt; to hear about the success of the &lt;a href=&quot;http://www.kickstarter.com/projects/ouya/ouya-a-new-kind-of-video-game-console&quot;&gt;OUYA&lt;/a&gt; and &lt;a href=&quot;http://www.kickstarter.com/projects/doublefine/double-fine-adventure&quot;&gt;Double Fine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: I see. Kickstarter unquestionably brought those projects to prominence, but are there examples of it working for unknown software-based products? OUYA is a hardware venture and Double Fine had Tim Schafer behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: Sure, &lt;a href=&quot;http://www.kickstarter.com/projects/eallam/try-ios-iphone-app-development-course?ref=category&quot;&gt;Code School&lt;/a&gt; just met their fundraising objectives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: But they had a tangible need for their fundraising. Mac Minis are expensive, and they made it very clear through how they would spend the funds to make the product possible. Essentially what you&amp;#39;re planning is to take pre-orders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: Well, basically. We have some more perks at various levels, but yeah it&amp;#39;s pre-ordering. It&amp;#39;s a much more visible place for our product to be than a temporal post on Hacker News or a few blogs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: But it&amp;#39;s also a much more visible place for your product to fizzle. Check &lt;a href=&quot;http://www.kickstarter.com/projects/2015210423/pixate-beautiful-native-mobile-apps-with-css&quot;&gt;Pixate&lt;/a&gt; or &lt;a href=&quot;https://join.app.net/&quot;&gt;App.net&lt;/a&gt;, which are well below their fundraising goals. They might have proven some tangible demand, but at what cost? By setting a &amp;quot;goal&amp;quot; you are also setting yourself up for possible failure. You may get a solid data-point in proving product-market fit, but it could also hurt your brand or future fundraising ambitions. What happens if you don&amp;#39;t meet your goal? You&amp;#39;ve done months of work, will you just pack it up? Because then you get none of the money and zero paying customers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;David&lt;/strong&gt;: We&amp;#39;re going to pick a less ambitious goal than those projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Socrates&lt;/strong&gt;: Well then what&amp;#39;s the point of going on Kickstarter at all? It sounds like you&amp;#39;re betting on a triumphant surge that makes you look like the Next Great Kickstarter Success. But in reality, most people just don&amp;#39;t get excited by software like they do with a new game console or 3D goggles.&lt;/p&gt;

&lt;p&gt;The customers who are excited about your product should find and buy your software regardless of the Kickstarter. The overlap between &amp;quot;people who go on Kickstarter&amp;quot; and &amp;quot;people who need your software&amp;quot; is probably very small, and you&amp;#39;ll find more success specifically targeting the latter group.&lt;/p&gt;

&lt;p&gt;There are less visible ways to prove your product is something people need. Talk to customers, run AdWords tests, get email signups, you know the drill. You have a working prototype: get it in users&amp;#39; hands. If it turns out you need to go back to the drawing board, then you can do so in private without losing face.&lt;/p&gt;

&lt;p&gt;Kickstarter isn&amp;#39;t a way out of hard work. If you know your customers, you should know how to directly market your product to them. Maybe you really do need crowd-funding for something, but make it clear what the money is going towards and why this product won&amp;#39;t exist without it. Don&amp;#39;t shoot yourself in the foot with a failed Kickstarter.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>The Shape Of Mobile Development To Come</title>
       <link href="http://clayallsopp.com/posts/the-shape-of-mobile-development-to-come"/>
       <updated>2012-07-29T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/the-shape-of-mobile-development-to-come</id>
       <content type="html">&lt;h1 id=&quot;toc_9188&quot;&gt;The Shape Of Mobile Development To Come&lt;/h1&gt;

&lt;p&gt;Mobile is still the exciting Wild West of today&amp;#39;s software. There&amp;#39;s only been about five years of modern development (not going to count the Java ME dark ages) and its best practices are still being discovered.&lt;/p&gt;

&lt;p&gt;I have some &amp;quot;long bets&amp;quot; about mobile development, which will hopefully come to fruition in the next two years. These are how I see (or would like to see) developer tools and processes evolve; maybe I&amp;#39;m totally wrong, but I&amp;#39;d love to hear what you think.&lt;/p&gt;

&lt;h2 id=&quot;toc_9189&quot;&gt;Tools Empowering Designers&lt;/h2&gt;

&lt;p&gt;Beautiful apps are hard to make. Designers are creating increasingly intricate and pixel-precise UIs, but porting these to actual code is a slow and painstaking process which usually leads to details getting lost in translation. The visuals alone are brilliant, but unfortunately what really matters is how they end up in a working product. For every rock-solid Path there are dozens of apps that have visible errors and discrepancies between what the design team intended and what engineering shipped.&lt;/p&gt;

&lt;p&gt;When I talk to mobile-centric startups, I always ask about the workflow between design and implementation. Several companies are trying to enforce rigorous oversight to make sure everything looks and feels correct, and that is definitely one solution to the problem. But the truly frictionless way is to create new tools that empower designers and take engineers out of the equation.&lt;/p&gt;

&lt;p&gt;Within the past few months, I feel there&amp;#39;s been a collective epiphany about this. &lt;a href=&quot;http://www.paintcodeapp.com&quot;&gt;PaintCode&lt;/a&gt; and &lt;a href=&quot;http://www.kickstarter.com/projects/2015210423/pixate-beautiful-native-mobile-apps-with-css&quot;&gt;Pixate&lt;/a&gt; are currently addressing aspects the problem, and I know of several unlaunched efforts in the pipeline. &lt;a href=&quot;http://www.markupwand.com&quot;&gt;MarkupWand&lt;/a&gt; and &lt;a href=&quot;http://csshat.com&quot;&gt;CSS Hat&lt;/a&gt; are really great ways this pain is being attacked on the web, and it would be interesting to see similar &amp;quot;PSD → Code&amp;quot; work done for mobile.&lt;/p&gt;

&lt;p&gt;Chopping assets, correcting alignments, and tweaking animations aren&amp;#39;t the core-competencies of a mobile engineer. Those tasks require many re-compilations and a continuous back-and-forth, taking up man-hours which could be put towards making the product stable and performant. Why should we keep producing our designs &amp;quot;twice&amp;quot; when converting the original might be within our grasp?&lt;/p&gt;

&lt;h2 id=&quot;toc_9190&quot;&gt;More Languages&lt;/h2&gt;

&lt;p&gt;&amp;quot;More languages&amp;quot; is generally true for all fields, but it especially proved true for the web. Writing backends gradually shifted from bare-metal compiled to higher-level scripting languages, and I think that trend will continue on mobile.&lt;/p&gt;

&lt;p&gt;For most of the past five years, there have basically been two choices: Java and Objective-C. Objective-C in particular has evolved over the past two years to become an &amp;quot;easier&amp;quot; language with the addition of ARC and improved literals, but given the choice I would still prefer something like Ruby for most work.&lt;/p&gt;

&lt;p&gt;Ruby turned out to be a winner on the web, so it&amp;#39;s not unreasonable to think it might happen again on our smartphones. I&amp;#39;ve written in the past about &lt;a href=&quot;http://rubymotion.com&quot;&gt;RubyMotion&lt;/a&gt;, and there&amp;#39;s also an Android counterpart &lt;a href=&quot;http://ruboto.org&quot;&gt;Ruboto&lt;/a&gt;. But there still more alternatives: &lt;a href=&quot;http://programming.nu/index&quot;&gt;Nu&lt;/a&gt; and Clojure &lt;a href=&quot;https://github.com/remvee/clj-android/&quot;&gt;for Android&lt;/a&gt; allow you to write apps in Lisp, and Scala was used &lt;a href=&quot;http://devblog.bu.mp/how-we-use-scala-in-bump-for-android&quot;&gt;in production at Bump&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Will developers stop writing apps in Objective-C and Java? Of course not; companies still write web code in C++ and Java. However, a greater variety of languages will undoubtedly help bridge mobile development to all sorts of new developers. That&amp;#39;s what gets me excited.&lt;/p&gt;

&lt;h2 id=&quot;toc_9191&quot;&gt;Better &lt;code&gt;CRUD&lt;/code&gt; Frameworks&lt;/h2&gt;

&lt;p&gt;When it comes down to it, there shouldn&amp;#39;t be a whole lot of business logic in most mobile software. All the heavy lifting should be done by servers, and apps act as (very pretty) shells for that data. They should cache  and gracefully degrade the experience during offline periods, but internal structure should always mirror and sync with what the server dictates.&lt;/p&gt;

&lt;p&gt;If that&amp;#39;s true, why aren&amp;#39;t there frameworks which make dealing with APIs as seamless as Rails makes interacting with a database? &lt;a href=&quot;https://github.com/AFNetworking/AFIncrementalStore&quot;&gt;AFIncrementalStore&lt;/a&gt; and &lt;a href=&quot;https://github.com/RestKit/RestKit/&quot;&gt;RESTKit&lt;/a&gt; are definitely steps in that direction, but they focus only on the API-Model relationship. Rails has the wonderful ability to generate views and forms based on models, so why don&amp;#39;t we do that too?&lt;/p&gt;

&lt;p&gt;Code speaks louder than words, so here are some ideas I&amp;#39;ve been playing around with (in Objective-C, but equally applicable to Java):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; : &lt;span class=&quot;nc&quot;&gt;MagicalFrameworkModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;find:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;success:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// User w/ ID 1, retrieved via API&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;failure:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}];&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Generates a UIViewController populated with correct&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// KVO for that class.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FormController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FormBuilder&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;controllerFor:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editUser&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;setUser:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navigationController&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;pushViewController:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editUser&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;animated:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;YES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Creates a UI element KVO-bound to property of a model&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FormTextField&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;observing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FormBuilder&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;textFieldFor:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;property:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I built some of that functionality into &lt;a href=&quot;https://github.com/clayallsopp/remote_model&quot;&gt;RemoteModel&lt;/a&gt;, but there&amp;#39;s a ton more to be done in the space. If we can make CRUD development on mobile that painless, we could iterate our mobile products much faster and with less underlying knowledge of how each platform works.&lt;/p&gt;

&lt;h2 id=&quot;toc_9192&quot;&gt;Web Apps?&lt;/h2&gt;

&lt;p&gt;I think there&amp;#39;s far more low-hanging fruit in making native development easier than in making web/hybrid apps feel &amp;quot;right&amp;quot;. I&amp;#39;ve seen two just good hybrid implementations (Quora and Pocket), and yet I still run into defects using both.&lt;/p&gt;

&lt;p&gt;The fact of the matter is there are hard technical limits to how far we can push web apps. Web views on all platforms generally eat memory and that, coupled with the &lt;a href=&quot;http://blog.mobtest.com/2012/05/heres-why-the-facebook-ios-app-is-so-bad-uiwebviews-and-no-nitro/&quot;&gt;lack of Nitro&lt;/a&gt; on iOS, means you have to put &lt;em&gt;a lot&lt;/em&gt; of work into making them fast and stable.&lt;/p&gt;

&lt;p&gt;I think the &amp;quot;write-once-run-everywhere&amp;quot; benefit of web views is disingenuous; the phrase should really go &amp;quot;write-once-optimize-everywhere&amp;quot;. There are specific nativization techniques that work better on each platform, plus some elements like text inputs won&amp;#39;t ever feel &amp;quot;right&amp;quot; when done using HTML and should be coded by hand. Heck, Apple&amp;#39;s App Store app feels terrible and they make the operating system!&lt;/p&gt;

&lt;p&gt;In the end, I don&amp;#39;t see web views getting very much closer to native apps than they are today. Facebook, the famous proponent of the whole web-native-hybrid idea, is reportedly shifting &lt;a href=&quot;http://bits.blogs.nytimes.com/2012/06/27/facebook-plans-to-speedup-its-iphone-app/?smid=tw-share&quot;&gt;back to native&lt;/a&gt;. The whole reason most companies use web views is (rightfully) writing two sets of app code is resource intensive. But what if there was another way...&lt;/p&gt;

&lt;h2 id=&quot;toc_9193&quot;&gt;True Write-Once-Run-Everywhere&lt;/h2&gt;

&lt;p&gt;This is the big bet, and the one I&amp;#39;m most likely to be wrong about. But if you take all of the above bets (more languages, abstractions for API communication, decoupling design from code) you can arrive at an interesting conclusion...&lt;/p&gt;

&lt;p&gt;What if you could write &lt;em&gt;true&lt;/em&gt; native apps for both iOS and Android with one codebase? All you need is a language that works on both platforms, like Ruby, and a level of abstraction above both MVC frameworks. The models would be easily portable, controllers on both platforms share a similar lifecycle, and with Auto-Layout coming to iOS perhaps there&amp;#39;s an easier way to map between iOS and Android views than we previously thought.&lt;/p&gt;

&lt;p&gt;Imagine writing code like this and having it build to native apps on both platforms:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ListController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Magic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MetaController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@list_view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ListView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@list_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;view_ready&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@row_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;These&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Are&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Rows&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@list_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@row_data&lt;/span&gt;

    &lt;span class=&quot;vi&quot;&gt;@list_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_tap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row_index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Tapped!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@row_data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row_index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &amp;quot;make a language that works on both platforms&amp;quot; is pretty hand-wavey, but if that can exist then I think we can do really incredible things.&lt;/p&gt;

&lt;p&gt;I&amp;#39;d love to hear your feedback about these wild ideas on &lt;a href=&quot;http://twitter.com/clayallsopp&quot;&gt;Twitter&lt;/a&gt; and &lt;a href=&quot;http://news.ycombinator.com/item?id=4309599&quot;&gt;Hacker News&lt;/a&gt;!&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>The RubyMotion Way</title>
       <link href="http://clayallsopp.com/posts/the-ruby-motion-way"/>
       <updated>2012-07-08T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/the-ruby-motion-way</id>
       <content type="html">&lt;h1 id=&quot;toc_9182&quot;&gt;The RubyMotion Way&lt;/h1&gt;

&lt;p&gt;I love &lt;a href=&quot;http://rubymotion.com&quot;&gt;RubyMotion&lt;/a&gt;. And the way things are looking now, I&amp;#39;ll never have to write Apple-platform software entirely in Objective-C again.&lt;/p&gt;

&lt;p&gt;Don&amp;#39;t get me wrong, I think Objective-C is a great language. I&amp;#39;ve enjoyed using it nearly every day for the past four years and it&amp;#39;s getting better all the time.&lt;/p&gt;

&lt;p&gt;But I find working in Ruby to be just plain fun. If you&amp;#39;ve tried projects in Ruby and just didn&amp;#39;t like it, RubyMotion probably won&amp;#39;t change your mind. But if you&amp;#39;ve ever wanted to make iOS or &lt;a href=&quot;http://macruby.org/&quot;&gt;Mac apps&lt;/a&gt; but didn&amp;#39;t want to get over the hump that is Objective-C, maybe this will get you going.&lt;/p&gt;

&lt;h2 id=&quot;toc_9183&quot;&gt;Rubyfication&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ve done some work on &lt;a href=&quot;http://bubblewrap.io&quot;&gt;BubbleWrap&lt;/a&gt;, which is the largest and most widely used RubyMotion gem. It aims to take all of the existing Cocoa frameworks and make them more pleasant in Ruby.&lt;/p&gt;

&lt;p&gt;The low-hanging fruit for this effort is taking the callback-centric Cocoa APIs, which are mostly handled in Objective-C using delegates or targets, and transitioning them to Ruby blocks. Here&amp;#39;s a quick comparison of handling button callbacks in Objective-C:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;addTarget:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;action:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;buttonTapped:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;forControlEvents:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UIControlEventTouchUpInside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//  Elsewhere&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;buttonTapped:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sender&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;and RubyMotion:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UIControlEventTouchUpInside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redColor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Pretty nice right? BubbleWrap and other efforts are systematically going through the Cocoa APIs and making things &lt;code&gt;lessLike:objectiveC:&lt;/code&gt; and more &lt;code&gt;like_ruby&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Some magical things are happening in the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattgreen/nitron&quot;&gt;Nitron&lt;/a&gt; makes CoreData more like ActiveRecord&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rubymotion/teacup&quot;&gt;Teacup&lt;/a&gt; adds stylesheets to &lt;code&gt;UIViews&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;My own project &lt;a href=&quot;https://github.com/clayallsopp/formotion&quot;&gt;Formotion&lt;/a&gt; lets you build interactive UIs with just a hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rubyists get a lot of flak for the kind of DSLs and black magic &lt;code&gt;method_missing&lt;/code&gt; tricks the above libraries use; but you know what, maybe that attitude is just what Objective-C has been missing.&lt;/p&gt;

&lt;h2 id=&quot;toc_9184&quot;&gt;Objective-Ruby&lt;/h2&gt;

&lt;p&gt;One of the criticisms of RubyMotion is that, while a solid technical achievement, it does not alleviate the pain that is the &lt;code&gt;verboseFunctionNames:inObjectiveC:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, that&amp;#39;s absolutely true. In fact, RubyMotion goes out of its way to preserve Cocoa APIs &lt;em&gt;exactly&lt;/em&gt; as intended. To keep Objective-C-style parameters, RubyMotion adds &lt;code&gt;new.functions(with, this: syntax)&lt;/code&gt;, which looks quite like &lt;code&gt;[old functions:with this:syntax]&lt;/code&gt; (Ruby 2.0 will have &lt;a href=&quot;http://rosettacode.org/wiki/Named_parameters#Ruby.27s_future&quot;&gt;the same sort of named arguments&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This is definitely a step up from other Objective-C bridges, which &lt;a href=&quot;http://mobiruby.org/&quot;&gt;pollute their languages&lt;/a&gt; &lt;a href=&quot;http://en.wikipedia.org/wiki/PyObjC#Messages_and_Methods&quot;&gt;with nasty hacks&lt;/a&gt;. I imagine that&amp;#39;s one reason why iOS development in other environments hasn&amp;#39;t caught on quite like RubyMotion has.&lt;/p&gt;

&lt;p&gt;Maybe another reason for RubyMotion&amp;#39;s relative success is that Objective-C, &lt;code&gt;[brackets]&lt;/code&gt; aside, is actually a &lt;em&gt;lot&lt;/em&gt; like Ruby. Notably, they use message passing for functions, which are interceptable and hackable in both languages. Objective-C has moved towards Ruby in recent years with blocks, literals (&lt;code&gt;@[]&lt;/code&gt;, &lt;code&gt;@{}&lt;/code&gt;), and indexes on normal objects (like &lt;code&gt;someNSObject[2]&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So actually, that &lt;code&gt;UIButton&lt;/code&gt; example from earlier? You can now write a wrapper in Objective-C that looks remarkably Ruby-like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;objc syntax&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;when:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIControlEventTouchUpInside&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But that&amp;#39;s not &amp;quot;the way&amp;quot; for most Objective-C developers, so there&amp;#39;s no similar movement towards adopting these nice wrappers.&lt;/p&gt;

&lt;p&gt;So I guess it turns out Objective-C is a language that&amp;#39;s nearly statically translatable to Ruby, so long as you don&amp;#39;t use lots of custom C in your iOS or Mac apps. And even if you do use some plain-old C, most of Apple&amp;#39;s C APIs and libraries actually &lt;a href=&quot;http://www.rubymotion.com/developer-center/guides/runtime/#_interfacing_with_c&quot;&gt;work as expected&lt;/a&gt; in RubyMotion!&lt;/p&gt;

&lt;h2 id=&quot;toc_9185&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;That all seems great, but do the niceties of Ruby come at a cost?&lt;/p&gt;

&lt;p&gt;Some are inherently skeptic of RubyMotion&amp;#39;s performance. That&amp;#39;s pretty reasonable, since normal Ruby has pretty dodgy performance. But there&amp;#39;s a giant difference between Ruby and RubyMotion: compilation.&lt;/p&gt;

&lt;p&gt;RubyMotion code is compiled to machine code and uses the Objective-C runtime. There&amp;#39;s no interpreter, no garbage collector, nothing except bare-metal machine code that looks basically identical to normal Objective-C. MacRuby does use the Objective-C 2.0 GC, but RubyMotion uses an ARC-like system for memory management like every other modern iOS app.&lt;/p&gt;

&lt;h2 id=&quot;toc_9186&quot;&gt;1.x&lt;/h2&gt;

&lt;p&gt;All that said, RubyMotion is still 1.x software. There are bugs in some under-used APIs, occasional memory management hiccups, and some tool flakiness.&lt;/p&gt;

&lt;p&gt;But damn does HipByte patch things quickly. Every time I&amp;#39;ve reported some weird behavior to &lt;a href=&quot;http://twitter.com/rubymotion&quot;&gt;@RubyMotion&lt;/a&gt;, it&amp;#39;s fixed within a week. And they aren&amp;#39;t just pushing bug fixes: the team continues to push awesome new features like better functional tests and static library compilation on a weekly basis. And if you want to contribute, part of the source is open to &lt;a href=&quot;https://github.com/HipByte/RubyMotion&quot;&gt;pull requests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unlike MacRuby, RubyMotion isn&amp;#39;t an internal project that Apple manages according to its resources. RubyMotion is an independent, commercial product with a passionate and amazingly talented team. They have a vested interest in continuing to make it better, and I&amp;#39;m incredibly excited to see where it goes from here.&lt;/p&gt;

&lt;h2 id=&quot;toc_9187&quot;&gt;Why not?&lt;/h2&gt;

&lt;p&gt;With all that RubyMotion can do, why aren&amp;#39;t you moving to use Ruby for your Apple apps &lt;em&gt;right this minute&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;I asked a friend a similar question the other day. He said learning iOS with RubyMotion would be like &amp;quot;starting front-end dev with jQuery&amp;quot;. At the moment, there&amp;#39;s a lot of truth in that statement. Knowing Ruby will only get you so far, as the Cocoa APIs which will make up 80% of your project are preserved in all their Objective-C glory.&lt;/p&gt;

&lt;p&gt;But that&amp;#39;s changing. The Rubyfication of Cocoa is going strong and some, myself included, are betting their money that it&amp;#39;s the way of the future. And in that future, all you need to make an app is idiomatic Ruby.&lt;/p&gt;

&lt;p&gt;So what are you waiting for? &lt;a href=&quot;http://rubymotion.com&quot;&gt;Get to it&lt;/a&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Blueprint for Building Native Apps</title>
       <link href="http://clayallsopp.com/posts/blueprint-for-building-native-apps"/>
       <updated>2012-06-28T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/blueprint-for-building-native-apps</id>
       <content type="html">&lt;h1 id=&quot;toc_9181&quot;&gt;Blueprint for Building Native Apps&lt;/h1&gt;

&lt;p&gt;How should companies build native mobile apps? I&amp;#39;ve thought &lt;em&gt;a lot&lt;/em&gt; about this very question. It&amp;#39;s a very different problem than web development, where you can push code 24/7 and bugs are cheap to fix. On mobile, you&amp;#39;ve got one shot to get it right and make a great first impression.&lt;/p&gt;

&lt;p&gt;(I&amp;#39;d probably augment this advice for larger teams, so apply this only to smaller startups)&lt;/p&gt;

&lt;p&gt;The first step is, &lt;strong&gt;as a team, step-through all the screens in your app&lt;/strong&gt;. Start with the question, &amp;quot;What is the very first thing the user sees when they download the app?&amp;quot;, and then explore what happens when they tap each button or perform all of the possible actions. Repeat exhaustively for each screen and be thorough. This needn&amp;#39;t be a 100% final UI mockup, just a bunch of boxes with arrows between them. This should give enough information for the engineers to start building a working &amp;quot;skeleton&amp;quot; of the app.&lt;/p&gt;

&lt;p&gt;Then &lt;strong&gt;fill in the screens with basic UI elements&lt;/strong&gt;. Where are all the buttons, text-boxes, or switches on each of them? Engineering can start coding with the normal looking UI elements which ship with the operating system.&lt;/p&gt;

&lt;p&gt;After you figure out the screens, &lt;strong&gt;list every piece of information you need on each of those screens&lt;/strong&gt;. Have a screen that lists books? What about them, their title, author, ISBN? Have a screen that shows details about a book? Do you show comments, reviews, ratings, or what? Even list what instructional or marketing copy is needed for different screens. Engineers can fill in those bare screens with working (but unstyled) data.&lt;/p&gt;

&lt;p&gt;While the engineers are filling in the bare-bones app with data and normal UI elements, your designers should start &lt;strong&gt;finalizing UI designs&lt;/strong&gt;. It&amp;#39;s basically taking your skeletons and doing this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.internetappdeveloper.com/archives/2741&quot;&gt;&lt;img src=&quot;http://qph.cf.quoracdn.net/main-qimg-70ad0d861dff868d4bb1e6f11e6ea694&quot; alt=&quot;Mobile UI conversion&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where the designers and engineers really need to collaborate. Your designer should supply specially formatted images for customizing buttons, navigation bars, tab bars, and other stock controls. The engineers should read up on &lt;a href=&quot;https://developer.apple.com/videos/wwdc/2012/&quot;&gt;Apple&lt;/a&gt; and Google&amp;#39;s docs on what the dimensions these need to be, but they should never have to open Photoshop and do it themselves. (I can tell you from personal experience, a coder playing with someone else&amp;#39;s design will probably screw it up anyway ;) ).&lt;/p&gt;

&lt;p&gt;Both iOS and Android support types of &amp;quot;stretchable&amp;quot; images (specified in code on iOS, as 9-patch PNGs on Android), which coders should familiarize your designer with. Also make sure all of the elements come prepared for multiple densities (so @2x on iOS, l/m/h/xh-DPI on Android).&lt;/p&gt;

&lt;p&gt;On mobile, it&amp;#39;s incredibly important to not only consider how something looks in a static photoshop file, but also how it looks in motion. Do elements animate? How should those animations behave, can they be prototyped by the designer to show to engineers? What do different buttons look like when they&amp;#39;re tapped or disabled? What do you show while images or data is loading from the server?&lt;/p&gt;

&lt;p&gt;My theory is that by the time UI styling and animations hit engineering, the design shouldn&amp;#39;t be changing much before launch. If you&amp;#39;re unsure about a design, try to prototype and get it in your hands somehow (Keynote, quick web demo, anything) before you resort to just trying it out using real Android or iOS code. In a perfect world, the designer would drop all of the specially sized UI elements in a Dropbox folder and the developers would be good-to-go.&lt;/p&gt;

&lt;p&gt;By the same token, designers should keep tabs on how well engineering is  implementing their work. Blurry graphics? Mis-aligned elements? Wrong fonts? These should all be called to attention and fixed.&lt;/p&gt;

&lt;p&gt;If you can&amp;#39;t tell by the body of this message, but in my experience &lt;strong&gt;that step takes 70-80% of the time&lt;/strong&gt;. A good engineer can whip up a working prototype pretty quick, but sweating the details and getting the UI right takes a lot of time. If anyone has found a better way for a custom-looking app, I&amp;#39;d love to hear about it!&lt;/p&gt;

&lt;p&gt;The last thing you need to do is &lt;strong&gt;test, test, test&lt;/strong&gt;. I&amp;#39;d try to get it in the hands of a small beta group (~30 people) and have them do regular, real-world use. Testing yourself will dead-end eventually and it&amp;#39;s always great to have fresh eyes. Products like &lt;a href=&quot;http://testflight.com/&quot;&gt;TestFlight&lt;/a&gt; are great for organizing those. And if you&amp;#39;re launching on Android...get as many devices as you can.&lt;/p&gt;

&lt;p&gt;And one more thing! After you launch, make sure you&amp;#39;re &lt;strong&gt;collecting data about app crashes and malfunctions&lt;/strong&gt;. Apple and Google do supply you with some crash statistics, but it&amp;#39;s always an under-representation of the truth. You can use services like &lt;a href=&quot;http://beta.crashlytics.com/&quot;&gt;Crashlytics&lt;/a&gt;, or you can roll your own with some easily available libraries. There&amp;#39;s nothing worse than your Twitter feed blowing up with customers saying, &amp;quot;App&amp;#39;s crashing at &lt;X screen&gt;&amp;quot; and you don&amp;#39;t have the data to reproduce it.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally an &lt;a href=&quot;http://www.quora.com/iPhone-Applications/Whats-the-best-step-by-step-guide-for-a-team-of-entrepreneurs-who-are-about-to-build-a-native-app-from-scratch/answer/Clay-Allsopp&quot;&gt;answer&lt;/a&gt; to a Quora question&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Formotion - Insanely Great Forms on iOS</title>
       <link href="http://clayallsopp.com/posts/better-forms-ios-formotion"/>
       <updated>2012-06-24T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/better-forms-ios-formotion</id>
       <content type="html">&lt;h1 id=&quot;toc_9180&quot;&gt;&lt;a href=&quot;http://github.com/clayallsopp/formotion&quot;&gt;Formotion&lt;/a&gt;: Better Forms on iOS&lt;/h1&gt;

&lt;p&gt;On mobile, we like to collect data. But we also like our apps to feel native, which creates a bit of a problem on iOS.&lt;/p&gt;

&lt;p&gt;See, the default Phone and Settings apps use grouped-style &lt;code&gt;UITableView&lt;/code&gt;s to retreive and present data. Coding these, especially with many different row variations, is a pain. &lt;/p&gt;

&lt;p&gt;So I wrote &lt;a href=&quot;http://github.com/clayallsopp/formotion&quot;&gt;Formotion&lt;/a&gt;, a RubyMotion library. With it, you can make this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/TMwXI.png&quot; alt=&quot;Complex data form&quot;&gt;&lt;/p&gt;

&lt;p&gt;using just this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Formotion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Register&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Email&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;me@mail.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;auto_correction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:no&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;auto_capitalization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:none&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;secure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;subtitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Confirmation&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:confirm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;secure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Remember?&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:switch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Account Type&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:account_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;select_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Free&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:basic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Pro&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:pro&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Sign Up&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@form_controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FormController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rootViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@form_controller&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And after the user enters some data, do this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;me@email.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;ss&quot;&gt;:confirm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:remember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:account_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:pro&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I think that&amp;#39;s pretty sweet.&lt;/p&gt;

&lt;p&gt;Check it out on &lt;a href=&quot;http://github.com/clayallsopp/formotion&quot;&gt;Github&lt;/a&gt;!&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Looking to iOS6</title>
       <link href="http://clayallsopp.com/posts/ios-6"/>
       <updated>2012-06-22T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/ios-6</id>
       <content type="html">&lt;h1 id=&quot;toc_9175&quot;&gt;Looking to iOS6&lt;/h1&gt;

&lt;p&gt;I was asked to go over my most anticipated features in iOS6, so here goes:&lt;/p&gt;

&lt;h6 id=&quot;toc_9176&quot;&gt;Auto-Layout&lt;/h6&gt;

&lt;p&gt;Already been said but Apple is doubling down on this and wants developers to take it seriously. At it&amp;#39;s simplest, instead of putting a button at (x: 138, y: 406), you describe it as being in the horizontal middle and 10 points from the bottom of it&amp;#39;s parent view. For the past five years, doing it the old way has worked fine because iPhones were always 320x480 and iPads were always 1024x768. But if Apple released a device or platform with new or variable dimensions, then these methods would break down (Apple has one such platform and already implemented Auto-Layout on it: OS X Lion).&lt;/p&gt;

&lt;p&gt;I wrote a long time ago in &lt;a href=&quot;http://www.quora.com/What-separates-the-iOS-SDK-from-the-Android-SDK/answer/Clay-Allsopp&quot;&gt;What separates the iOS SDK from the Android SDK?&lt;/a&gt; that a big differentiator between iOS and Android is how UIs are coded. Although Apple hasn&amp;#39;t gone so far as to add an XML structure for interfaces, Auto-Layout does bring the two platforms (a tiny bit) closer in mindset. It invalidates a lot of old tutorials and books and will take some getting used to, but it really is for the better.&lt;/p&gt;

&lt;p&gt;Maybe Apple won&amp;#39;t release a different form factor or platform in the near-future, but it would be naive to think that we&amp;#39;ll forever and always deal with the above two resolutions (or retina scales of them). Auto-Layout the future, and you should code to support it.&lt;/p&gt;

&lt;h6 id=&quot;toc_9177&quot;&gt;Passbook/Pass Kit&lt;/h6&gt;

&lt;p&gt;I really like this one, but it&amp;#39;s definitely a more complex architecture for developers. If you&amp;#39;re making an app or website which interacts with real-world goods or experiences, you can store items relating to it in the user&amp;#39;s Passbook. Apple gives examples like boarding passes, coupons, tickets, and membership cards.&lt;/p&gt;

&lt;p&gt;To implement it, you generate a bunch of information on your server about the pass (all the text, styles, identifiers, etc...there&amp;#39;s just a load of options you can use). iOS6 will install this pass data through your app, an email, or a web link. You can use your app to edit existing passes, but they must be constructed on the server. There&amp;#39;s also a lot of work to be done in keeping passes in-sync between client and server (did the user change their seats? upgrade their membership? stuff like that).  Good opportunity for a Ruby library to help out with this stuff.&lt;/p&gt;

&lt;p&gt;As a user, this is what I&amp;#39;m the most excited about. There are multiple startups  already trying to solve the same problem, but Apple has the sheer size and pull to make it go mainstream. Color me excited.&lt;/p&gt;

&lt;h6 id=&quot;toc_9178&quot;&gt;Privacy&lt;/h6&gt;

&lt;p&gt;After the giant contacts-privacy debacle, Apple has added privacy dialogs for most pieces of user data (location, contacts, calendars, reminders, photos). Backwards compatibility exists if permission is denied by returning no data in pre-iOS6 apps, but new apps will need to monitor for changes in permission to refresh their data (i.e. I change my mind about denying your app my contact data, so I allow it in Settings.app).&lt;/p&gt;

&lt;h6 id=&quot;toc_9179&quot;&gt;Identifiers&lt;/h6&gt;

&lt;p&gt;Apple made a big hubbub when they deprecated UIDevice#uniqueIdentifier. In iOS6, there is a distinction between identifiers for advertisers and identifiers for vendors (i.e. your ID on all the apps that Facebook makes). Use the global advertiser ID only when necessary.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally an &lt;a href=&quot;http://www.quora.com/iOS-Development/From-a-developers-perspective-what-new-and-interesting-features-and-notable-changes-are-in-the-iOS-6-SDK&quot;&gt;answer&lt;/a&gt; to a Quora question&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>☆ The First Summer</title>
       <link href="http://clayallsopp.com/posts/first-summer"/>
       <updated>2012-06-22T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/first-summer</id>
       <content type="html">&lt;h1 id=&quot;toc_9174&quot;&gt;☆ The First Summer&lt;/h1&gt;

&lt;p&gt;What I did one summer three years ago has shaped my life ever since.&lt;/p&gt;

&lt;p&gt;I was 17 and armed with my first-generation iPhone. I had been trying to get into iPhone development ever since the SDK came out about a year prior but hadn&amp;#39;t really got anywhere due to school. Summer came and I took it as an opportunity to buckle down and get something on the App Store.&lt;/p&gt;

&lt;p&gt;I got about halfway through &lt;a href=&quot;http://www.amazon.com/Beginning-iPhone-Development-Exploring-SDK/dp/1430216263&quot;&gt;Beginning iPhone Development&lt;/a&gt; and decided I was capable of a basic table-based app. Naturally, what came to mind was a database of....brocabulary. Some friends and I were going through a period of dropping these whenever possible and it was getting awfully hard to remember all of our permutations. What else is a hacker to do but solve their own problems?&lt;/p&gt;

&lt;p&gt;Spent about two weeks coding up the app and brainstorming with my friends for the ~100 initial terms. Submitted to the App Store around the middle of June (right around the time OS 3.0 was released) and was released a week later under the title &lt;a href=&quot;http://itunes.apple.com/us/app/brocabulary-new-and-improved/id320767043?mt=8&amp;amp;ls=1&quot;&gt;Brocabulary&lt;/a&gt;. Got some downloads, made a bit of money ($0.99 per purchase), and was instantly hooked on making apps. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://qph.cf.quoracdn.net/main-qimg-e0661c99a8403f60b52ba8491d0f9bc6&quot; alt=&quot;Brocabulary&quot;&gt;&lt;/p&gt;

&lt;p&gt;I mean really, how awesome was it that I could make something in my bedroom that a) made money and b) complete strangers told me they enjoyed?&lt;/p&gt;

&lt;p&gt;So that was my first few weeks of summer. For my next project I decided that I wanted to do a game, albeit something simple enough that I could actually ship. Most iPhone games used the accelerometer for their functionality, but I wanted something more unique. I looked at all the features of the iPhone and decided the microphone was underrepresented on the App Store. I came up with the idea of blowing into it to push a paper plane.&lt;/p&gt;

&lt;p&gt;The crucial part was figuring out how to measure the input of the microphone, which I adapted from some code I found on StackOverflow. I utilized the relatively nascent Cocos2D&lt;a href=&quot;http://www.cocos2d-iphone.org/&quot;&gt;2&lt;/a&gt; game engine to make life easier. At the time I didn&amp;#39;t know any backend technologies, so I went with the now-defunct scoreboard hosting service &lt;a href=&quot;http://code.google.com/p/cocoslive/&quot;&gt;CocosLive&lt;/a&gt; to store how long players &amp;quot;blew&amp;quot; for. After about another two weeks of work, &lt;a href=&quot;http://itunes.apple.com/us/app/paper-planes/id323274806?mt=8&amp;amp;ls=1&quot;&gt;Paper Planes&lt;/a&gt; was ready.&lt;/p&gt;

&lt;p&gt;It went live on the App Store in mid-July and got something like 1,000 downloads on the first day. That was HUGE to me, since Brocabulary had only gotten ~200 downloads in its entire (young) life. Immediately I sent in an update which placed an ad on the scoreboard screen, in hopes of getting some small revenue ;) (in the end I wound up with a couple hundred dollars). Since then, it&amp;#39;s gone on to get about a million downloads during it&amp;#39;s lifetime.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://qph.cf.quoracdn.net/main-qimg-68da02d4b645ff710ac54203bb988c34&quot; alt=&quot;Paper Planes&quot;&gt;&lt;/p&gt;

&lt;p&gt;I worked on some other apps over the remainder of the summer but I feel like this covers the important parts.&lt;/p&gt;

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

&lt;p&gt;I went from merely taking computer science classes in school to making products that shipped to thousands of people, all in a matter of months. From then on I knew there was nothing quite like software for me. In retrospect the code was rough and the apps were a little buggy, but a kid has to start somewhere right?&lt;/p&gt;

&lt;p&gt;I wrote about my experience making apps in all my college essays, and I think it played a big part in my admission to UC Berkeley. I got out to California and dove into the hacker scene, using my iOS skills as an inroad. One thing led to another and suddenly I&amp;#39;m cofounder of a Y-Combinator startup, making an iPad app. I&amp;#39;ve gone on to help build beautiful iOS and Android apps (&lt;a href=&quot;http://discovercircle.com&quot;&gt;Circle&lt;/a&gt;), and am now a Thiel Fellow working on app-related tools.&lt;/p&gt;

&lt;p&gt;Without that one summer learning iOS development, none of that would&amp;#39;ve happened.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally an &lt;a href=&quot;http://www.quora.com/Startup-Founders-and-Entrepreneurs/When-you-were-a-teenager-what-was-the-most-creative-thing-you-did-in-summer/answer/Clay-Allsopp&quot;&gt;answer&lt;/a&gt; to a Quora question&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Android Best Practices and Tips</title>
       <link href="http://clayallsopp.com/posts/android-best-practices-tips"/>
       <updated>2012-06-22T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/android-best-practices-tips</id>
       <content type="html">&lt;h1 id=&quot;toc_9173&quot;&gt;Android Best Practices and Tips&lt;/h1&gt;

&lt;p&gt;I may have cut my teeth on iOS, but I have a soft spot for Android.&lt;/p&gt;

&lt;p&gt;On one hand, it&amp;#39;s much easier to create fluid, scalable layouts using their XML system. And thankfully, independent Activities make it difficult to write the spaghetti code you might find in poorer iOS apps (&lt;code&gt;self.navigationController.viewControllers[2]&lt;/code&gt; anyone?).&lt;/p&gt;

&lt;p&gt;But then again, it&amp;#39;s Java (&lt;code&gt;ProblemFactory&lt;/code&gt; anyone?), and Google keeps changing their minds about what good apps should look like (see: 4.0 being a total rewrite of their interface guidelines).&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve worked on some really beautiful Android apps (&lt;a href=&quot;http://discovercircle.com&quot;&gt;Circle&lt;/a&gt;), so I thought I&amp;#39;d share some knowledge I&amp;#39;ve picked up along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;a href=&quot;http://code.google.com/p/roboguice/&quot;&gt;RoboGuice&lt;/a&gt;&lt;/strong&gt;, Google&amp;#39;s port of Guice to Android. Takes out a LOT of glue code with both plain-Java dependency injection and really awesome view injections (see &lt;a href=&quot;http://code.google.com/p/roboguice/wiki/SimpleExample&quot;&gt;this&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn the &lt;a href=&quot;http://i.imgur.com/rPrTr.png&quot;&gt;Activity lifecycle&lt;/a&gt;&lt;/strong&gt;. Remember to zero any dangling references at the correct times so leaks don&amp;#39;t occur (so your on[Create/Start/Resume] should basically mirror your on[Destroy/Stop/Pause]).&lt;/li&gt;
&lt;li&gt;Speaking of Activities, &lt;strong&gt;be wary of controllers/activities getting thick&lt;/strong&gt;. On mobile there&amp;#39;s a temptation to do a lot of animation or layout logic in the controllers. Create tertiary objects (&amp;quot;presenters&amp;quot;) which handle animations + UI-only logic, which the activities call when necessary.&lt;/li&gt;
&lt;li&gt;Design your views so they flow and expand to &lt;strong&gt;multiple sizes/orientations&lt;/strong&gt;. Don&amp;#39;t make them absolutely positioned or sized, so use &lt;code&gt;dip&lt;/code&gt;s for your measurements and align views relatively.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn and use &lt;a href=&quot;http://developer.android.com/guide/components/fragments.html&quot;&gt;Fragments&lt;/a&gt; now&lt;/strong&gt;. They&amp;#39;re relatively new in Android-land, available on phones only since 4.0, but Google is deprecating many older APIs in favor of new Fragment-based ones. They&amp;#39;re sort of like embeddable Activities, which means you can take one Fragment you used as an entire Activity on a phone and use it as a component of a larger interface on a tablet. Kind of neat, right?&lt;/li&gt;
&lt;li&gt;In general, &lt;strong&gt;practice good MVC&lt;/strong&gt;. Activities should just take data from the models and insert them into the views, or take events from a view and tell the data to do something. Don&amp;#39;t run URL requests or other raw data fetches in controllers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn the &lt;a href=&quot;http://i.imgur.com/rPrTr.png&quot;&gt;Activity lifecycle&lt;/a&gt;&lt;/strong&gt;. Intentional repetition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do those and you&amp;#39;re on your way to having a solid Android app.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally an &lt;a href=&quot;http://www.quora.com/Android-Development/What-are-some-best-practices-in-Android-coding-patterns/answer/Clay-Allsopp&quot;&gt;answer&lt;/a&gt; to a Quora question&lt;/em&gt;&lt;/p&gt;
</content>
     </entry>
     
 
     
     <entry>
       <title>Container and Child UIViewControllers</title>
       <link href="http://clayallsopp.com/posts/child-container-controllers"/>
       <updated>2012-06-21T00:00:00-07:00</updated>
       <id>http://clayallsopp.com/posts/child-container-controllers</id>
       <content type="html">&lt;h1 id=&quot;toc_9169&quot;&gt;Container and Child UIViewControllers&lt;/h1&gt;

&lt;p&gt;Historically, iOS developers have been limited to just two batteries-included ways of organizing their apps: &lt;code&gt;UINavigationController&lt;/code&gt;s and &lt;code&gt;UITabBarController&lt;/code&gt;s. These are &lt;code&gt;UIViewController&lt;/code&gt;s, but are unique in that they organize other &lt;code&gt;UIViewController&lt;/code&gt;s as part of their content. Prior to iOS5, there was no formal way of doing the same in a custom manner; you could either manage your own view controller relationships or use one mega-controller with a complex view hierarchy. But what about today, &lt;em&gt;after&lt;/em&gt; iOS5?&lt;/p&gt;

&lt;p&gt;Now we have a concise set of functions in &lt;code&gt;UIViewController&lt;/code&gt; to add or remove &amp;quot;child&amp;quot; view controllers to a &amp;quot;parent&amp;quot; view controller.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s say we want to implement a vertical &lt;code&gt;UINavigationController&lt;/code&gt;, where pushing a new view controller is transitioned by a vertical slide (instead of the horizontal default).&lt;/p&gt;

&lt;p&gt;First we define a &lt;code&gt;UIViewController&lt;/code&gt; subclass as the container controller; lets call it &lt;code&gt;VerticalNavigationController&lt;/code&gt;. &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VerticalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIViewController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loadView&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initWithFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UIScreen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mainScreen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;applicationFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Pretty straightfoward: we created a view sized to fits the screen. You can add whatever &amp;quot;chrome&amp;quot; (navigation bar, tabs, etc) at this point.&lt;/p&gt;

&lt;p&gt;Time to start working on how to get our &amp;quot;children&amp;quot; controllers in there. We need an exposed API to do this, so let&amp;#39;s do something similar to how &lt;code&gt;UINavigationController&lt;/code&gt; works. It&amp;#39;s usually nice to design systems by writing public methods like these before then writing the internal components:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VerticalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIViewController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We know that these two methods should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add/remove the view controller to some kind of internal stack.&lt;/li&gt;
&lt;li&gt;Add/remove the view controller as a child VC via UIKit&amp;#39;s methods.&lt;/li&gt;
&lt;li&gt;Add/remove the view controller&amp;#39;s view to our container&amp;#39;s view hierarchy.&lt;/li&gt;
&lt;li&gt;Animate the addition/removal of the view controller&amp;#39;s view, if applicable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&amp;#39;s hammer those out, shall we?&lt;/p&gt;

&lt;p&gt;First, the stack. Ruby has some nice methods for treating &lt;code&gt;Array&lt;/code&gt;s as stacks, so we&amp;#39;ll just build ontop of those, using our container&amp;#39;s &lt;code&gt;#push&lt;/code&gt;/&lt;code&gt;#pop&lt;/code&gt; as a thin proxy for the real &lt;code&gt;stack&lt;/code&gt;. &lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VerticalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIViewController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stack&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# could be nil&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# If we have 0 or 1 view controllers, don&amp;#39;t pop.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We do some nice checks in &lt;code&gt;#pop&lt;/code&gt; to make sure we don&amp;#39;t pop to an empty stack. I established some semantics to make our lives easier: the controller we&amp;#39;re going to display will be &lt;code&gt;to_vc&lt;/code&gt;, and the one we&amp;#39;re hiding is &lt;code&gt;from_vc&lt;/code&gt;, regardless whether we&amp;#39;re pushing or popping.&lt;/p&gt;

&lt;p&gt;Next on our list, we need to add the &lt;code&gt;UIViewController&lt;/code&gt; methods for adding child controllers (say that five times fast). They are:&lt;/p&gt;

&lt;h6 id=&quot;toc_9170&quot;&gt;Adding Children&lt;/h6&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;willMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addChildViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;didMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9171&quot;&gt;Removing children&lt;/h6&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;willMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;removeFromParentViewController&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;didMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h6 id=&quot;toc_9172&quot;&gt;Both&lt;/h6&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transitionFromViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;toViewController&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:UIViewAnimationOptionTransitionNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;animations&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In practice, &lt;code&gt;addChildViewController&lt;/code&gt; calls &lt;code&gt;willMoveToParentViewController(container)&lt;/code&gt; and  &lt;code&gt;removeFromParentViewController&lt;/code&gt; calls &lt;code&gt;didMoveToParentViewController(nil)&lt;/code&gt;, so you only need to use four of those in your implementation (this doesn&amp;#39;t happen if you override &lt;code&gt;automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers&lt;/code&gt;, but let&amp;#39;s ignore that for now).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;transitionFromViewController&lt;/code&gt; will handle adding/removing subviews from &lt;code&gt;container&lt;/code&gt;&amp;#39;s &lt;code&gt;vier&lt;/code&gt;, so that&amp;#39;s even less code you need to worry about.&lt;/p&gt;

&lt;p&gt;Armed with this new knowledge, let&amp;#39;s flesh out our implementation a bit more.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre class='codehilite'&gt;&lt;code class=&quot;ruby syntax&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VerticalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UIViewController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# could be nil&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addChildViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# transitionFromViewController: breaks if from_vc.nil?&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# so need to handle it as a special case.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewWillAppear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewDidAppear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;didMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewWillAppear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transitionFromViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
          &lt;span class=&quot;ss&quot;&gt;toViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;ss&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;ss&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UIViewAnimationOptionTransitionNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;animations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                              &lt;span class=&quot;c1&quot;&gt;# do some animations&lt;/span&gt;
                           &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewDidAppear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

                    &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;didMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;willMoveToParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewWillDisappear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transitionFromViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
              &lt;span class=&quot;ss&quot;&gt;toViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_vc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;ss&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;ss&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UIViewAnimationOptionTransitionNone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;animations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                                  &lt;span class=&quot;c1&quot;&gt;# do some animations&lt;/span&gt;
                               &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                    &lt;span class=&quot;ss&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;removeFromParentViewController&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;from_vc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewDidDisappear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It seems like a lot of code, but only because the &lt;code&gt;transitionFromViewController&lt;/code&gt;s are broken into multiple lines. Let&amp;#39;s walk through it.&lt;/p&gt;

&lt;p&gt;In each function we find what controller we&amp;#39;re going to and what controller we&amp;#39;re coming from. Then we call &lt;code&gt;willMoveToParentViewController&lt;/code&gt; on them (we don&amp;#39;t do so in &lt;code&gt;#push&lt;/code&gt; because &lt;code&gt;addChildViewController&lt;/code&gt; handles that).&lt;/p&gt;

&lt;p&gt;Next we handle what happens to their &lt;code&gt;view&lt;/code&gt;s. Remember to call the &lt;code&gt;view[Will/Did]Appear&lt;/code&gt; and &lt;code&gt;view[Will/Did]Disappear&lt;/code&gt; at the appropriate times (before/after adding/removing it as a subview). We call all the &lt;code&gt;didX&lt;/code&gt; methods when we&amp;#39;re done with our animations in &lt;code&gt;transitionFromViewController&lt;/code&gt;. The only code that does anything differently is &lt;code&gt;#push&lt;/code&gt;, which will force a manual addition of the new controller&amp;#39;s &lt;code&gt;view&lt;/code&gt; because there is no &lt;code&gt;from_vc&lt;/code&gt; sometimes.&lt;/p&gt;

&lt;p&gt;And that&amp;#39;s about all you need! Just plug in your custom animations or chrome and you&amp;#39;re good to go.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve uploaded &lt;a href=&quot;https://github.com/clayallsopp/motion-tips/tree/master/1-child-controllers/Children&quot;&gt;a more complete example&lt;/a&gt;. It&amp;#39;s ugly, but shows how to do animations and lock a navigation bar to top of the container&amp;#39;s &lt;code&gt;view&lt;/code&gt;.&lt;/p&gt;
</content>
     </entry>
     
 
 
</feed>