<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>
This is the web log of High Order Bit, makers of great software for iPhone and iPad. Learn more about us on our website, or follow us on Twitter.


Follow @highorderbit
We Make

      
    
    
      Chirpy
    
  
      
    
    
      Twitbit
    
  
      
    
    
      GPS Tracks
    
  
      
    
    
      Notekeeper
    
  </description><title>High Order Blog</title><generator>Tumblr (3.0; @highorderbit)</generator><link>http://weblog.highorderbit.com/</link><item><title>Appropriate Use of C Macros for Objective-C Developers</title><description>&lt;p&gt;I&amp;#8217;ve been writing software for iOS full time for almost 3 years. During that time, I&amp;#8217;ve noticed an increasing number of developers using &lt;a href="http://en.wikipedia.org/wiki/C_preprocessor"&gt;C macros&lt;/a&gt; for operations where they&amp;#8217;re not necessary, and could be more effectively replaced with either C functions or Objective-C methods.&lt;/p&gt;

&lt;p&gt;C macros come with a host of problems that are well known to C and C++ programmers. There are situations where they provide unique functionality, but those situations are rare. My rough sense is that many members of the exploding iOS community are coming from a Java, Python, or Ruby background, and don&amp;#8217;t have deep experience with a C-based language. Many of these developers don&amp;#8217;t have a thorough understanding of how easy it is for macros to cause subtle and unexpected problems. There&amp;#8217;s nothing wrong with this; learning the nooks and crannies of an archaic language like Objective-C takes time. It takes making lots of mistakes. Hopefully I can help a few people avoid some that I&amp;#8217;ve tripped over in the past.&lt;/p&gt;

&lt;p&gt;Macros are preprocessor definitions. What this means is that before your code is compiled, the preprocessor scans your code and, amongst other things, substitutes the definition of your macro wherever it sees the name of your macro. It doesn&amp;#8217;t do anything more clever than that. Almost literal code substitution. There are plenty of &lt;a href="http://www2.research.att.com/~bs/bs_faq2.html#macro"&gt;great explanations&lt;/a&gt; online of the kinds of subtle and not-so-subtle problems they can cause. I&amp;#8217;ll give one extremely simple example here.&lt;/p&gt;

&lt;p&gt;Suppose you want a method to return the maximum of two numbers. You write a macro to do this simple task:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define MAX(x, y) x &amp;gt; y ? x : y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple, right? You then use the macro in your code like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;int a = 1, b = 2;
int result = 3 + MAX(a, b);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Looks innocent. The problem is that the preprocessor substitutes the macro definition into the code before compilation, so this is the code the compiler sees:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;int a = 1, b = 2;
int result = 3 + a &amp;gt; b ? a : b;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;C order of operations requires the sum &lt;code&gt;3 + a&lt;/code&gt; be calculated before the ternary operator is applied. You intended to save the value of &lt;code&gt;3 + 2&lt;/code&gt; in &lt;code&gt;result&lt;/code&gt;, but instead you add 3 + 1 first, and test if the sum is greater than 2, which it is. Thus &lt;code&gt;result&lt;/code&gt; equals &lt;code&gt;2&lt;/code&gt;, rather than the 5 you expected.&lt;/p&gt;

&lt;p&gt;Already alarm bells should be going off. But you&amp;#8217;ve come this far, so you fix the problem by adding some parentheses and try again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define MAX(x, y) ((x) &amp;gt; (y) ? (x) : (y))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Seems to work now. You breath an uneasy sigh of relief. You continue along on your project until you have this code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;int a = 1, b = 2;
int result = MAX(++a, ++b);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the preprocessor runs, this expands to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;int result = ((++a) &amp;gt; (++b) ? (++a) : (++b));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Parentheses can&amp;#8217;t save you now. Whichever value is greater is going to be incremented twice, not once. This is almost certainly not what you intended. Now you know you&amp;#8217;re doing something wrong, and you start to look around for alternatives.&lt;/p&gt;

&lt;p&gt;So what&amp;#8217;s a better way? It&amp;#8217;s simple. Just write a function. Functions are easy to write, easy to read, state your intent clearly, and the compiler has all kinds of optimization tricks it can apply if appropriate. A &lt;code&gt;max&lt;/code&gt; function is trivially written as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;int max(int x, int y)
{
    return x &amp;gt; y ? x : y;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Done. No subtle errors, no seemingly random bugs causing you to rip your hair out, bashing your head against the keyboard, ruing the day you decided to become a programmer. And for Objective-C developers, rest assured that there&amp;#8217;s no reason you can&amp;#8217;t mix in C functions into your code. If you&amp;#8217;ve ever written any CFNetworking or Quartz 2D code, you&amp;#8217;re calling C methods.&lt;/p&gt;

&lt;h3&gt;Don&amp;#8217;t Use Macros to Define Constants&lt;/h3&gt;

&lt;p&gt;Probably the most common macro use is to define a constant:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define NUM_THREADS 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here it&amp;#8217;s better to use a static const integer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;static const NSInteger NUM_THREADS = 4;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The advantages over the macro are that the value of the variable can be viewed in the debugger, it respects scope according to the rules of the language, and it&amp;#8217;s type-safe.&lt;/p&gt;

&lt;h3&gt;Prefer Functions or Categories over Macros for Helper Methods&lt;/h3&gt;

&lt;p&gt;Some people tote around header files full of frequently used macros, most of which should probably be functions or class categories. Consider detecting whether your app is running on an iPad. You can write this as a macro like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define IS_PAD [[UIDevice currentDevice] interfaceIdiom] == UIUserInterfaceIdiomPad)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make no mistake, though, that this brings along all the subtle problems of macros generally as demonstrated above.&lt;/p&gt;

&lt;p&gt;One way to rewrite this is simply as a category on UIDevice (I&amp;#8217;m only showing the implementation portion):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@implementation
- (BOOL)isPad
{
    return [self interfaceIdiom] == UIUserInterfaceIdiomPad;
}
@end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then it can be used easily:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ([[UIDevice currentDevice] isPad])
    // my iPad specific code
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or the macro can easily be rewritten as a C function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(BOOL)isPad()
{
    return [[UIDevice currentDevice] interfaceIdiom] == UIUserInterfaceIdiomPad;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Both are simple and clear, respect scope, are type-safe, etc. Unless you have some extremely special case, this should be the preferred way to write helper methods.&lt;/p&gt;

&lt;h3&gt;Appropriate Use of Macros&lt;/h3&gt;

&lt;p&gt;There are occasions where macros provide necessary functionality not available through other means. One example is when you do need to actually have the context of the current code location at hand when the code executes.&lt;/p&gt;

&lt;p&gt;For example, I have a simple macro I sometimes use when debugging Objective-C to log when certain methods are called. This can be done like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NSLog(@"%@: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can&amp;#8217;t be moved into an Objective-C method because it will always log the name of that method. (Obviously it can&amp;#8217;t be moved into a C method, as there is no self and no _cmd variables available.) Creating a macro for this is straightforward, however:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define LOG_SELECTOR()  NSLog(@"%@: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In  a case like this, the only option is to use macros. That&amp;#8217;s fine. Macros are a tool in one&amp;#8217;s tool belt, so to speak. It&amp;#8217;s great to use them when appropriate. But it&amp;#8217;s important to understand their limitations, and to know what alternatives are available and why they should be preferred.&lt;/p&gt;</description><link>http://weblog.highorderbit.com/post/11656225202</link><guid>http://weblog.highorderbit.com/post/11656225202</guid><pubDate>Wed, 19 Oct 2011 10:32:00 -0600</pubDate></item><item><title>Introducing TwitterKit, a Library for Simple Twitter Integration for iOS and Mac Apps</title><description>&lt;a href="http://jad.debay.net/post/10492232340"&gt;Introducing TwitterKit, a Library for Simple Twitter Integration for iOS and Mac Apps&lt;/a&gt;: &lt;p&gt;From my &lt;a href="http://jad.debay.net/post/10492232340" class="tumblr_blog"&gt;personal blog&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Twitter integration is a common requirement of iPhone apps. Indeed, two of the apps &lt;a href="http://highorderbit.com" target="_blank"&gt;my company&lt;/a&gt; sells are built around Twitter. Many other apps I’ve worked on for clients have also required Twitter integration.&lt;/p&gt;

&lt;p&gt;
I’m hoping to make that job a little easier for other iOS (and Mac) developers in the future by releasing TwitterKit, a simple and lightweight library for communicating with the Twitter REST API. TwitterKit should work with iOS 4.0 and up, and Mac OS X 10.6 and up.
&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://weblog.highorderbit.com/post/10493834429</link><guid>http://weblog.highorderbit.com/post/10493834429</guid><pubDate>Wed, 21 Sep 2011 15:59:10 -0600</pubDate></item><item><title>Will iCloud Be Easy for Developers?</title><description>&lt;a href="http://jad.debay.net/post/6555727897"&gt;Will iCloud Be Easy for Developers?&lt;/a&gt;: &lt;p&gt;From my &lt;a href="http://jad.debay.net/post/6555727897" class="tumblr_blog"&gt;personal blog&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s one thing for Apple to nail data sync for their operating systems and their core applications like iWork. They have the expertise and the resources to devote to getting it just right. It’s another thing entirely to develop a general framework in which your average developer can nail data sync for their own applications.
&lt;/p&gt;

&lt;p&gt;
Making things easy for developers is a crucial component of success in moving adoption of any technology. iCloud is no different. Apple is trying to make it as simple and transparent as possible for app developers. We just need to see how &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;leaky the abstraction&lt;/a&gt; will be in practice.
&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://weblog.highorderbit.com/post/6556885871</link><guid>http://weblog.highorderbit.com/post/6556885871</guid><pubDate>Wed, 15 Jun 2011 10:34:52 -0600</pubDate></item><item><title>High Order Bit's WWDC 2011 App Sale Blowout</title><description>&lt;p&gt;Next week is &lt;a href="http://developer.apple.com/wwdc/"&gt;WWDC 2011&lt;/a&gt;, the biggest event of the year for Mac and iOS developers. To celebrate the occasion, we&amp;#8217;re putting all of our apps on sale for $0.99 each all week. As a bonus, even though WWDC doesn&amp;#8217;t start until Monday, our sale is going to start today and run until Friday, June 10th.&lt;/p&gt;

&lt;p&gt;That means you can get the all new hotness that is &lt;a href="http://itunes.apple.com/us/app/chirpy-for-twitter-direct/id370400161?mt=8"&gt;Chirpy 2.0&lt;/a&gt;, &lt;a href="http://itunes.apple.com/us/app/twitbit/id322281538?mt=8"&gt;GPS Tracks&lt;/a&gt;, &lt;a href="http://itunes.apple.com/us/app/gps-tracks-track-location/id367384269?mt=8"&gt;Twitbit&lt;/a&gt;, and &lt;a href="http://itunes.apple.com/us/app/notekeeper/id381190368?mt=8"&gt;Notekeeper&lt;/a&gt; for a combined price of $3.96. That&amp;#8217;s less than the price of a latte at Starbucks. Ridiculous I know, but that&amp;#8217;s just how much we love you.&lt;/p&gt;

&lt;p&gt;As they say on TV, don&amp;#8217;t wait! Act now!&lt;/p&gt;

&lt;table border="0" cellspacing="15" cellpadding="0"&gt;&lt;tr&gt;&lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/chirpy-for-twitter-direct/id370400161?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm74vfVpvK1qfjldc.png" alt="Chirpy"/&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/twitbit/id322281538?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm752lSqgd1qfjldc.png" alt="Twitbit"/&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/gps-tracks-track-location/id367384269?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm75c9hivi1qfjldc.png" alt="GPS Tracks"/&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/notekeeper/id381190368?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm75g99oYB1qfjldc.png" alt="Notekeeper"/&gt;&lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/chirpy-for-twitter-direct/id370400161?mt=8"&gt;Chirpy 2.0&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/twitbit/id322281538?mt=8"&gt;Twitbit&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/gps-tracks-track-location/id367384269?mt=8"&gt;GPS Tracks&lt;/a&gt;
    &lt;/td&gt;
    &lt;td align="center"&gt;
      &lt;a href="http://itunes.apple.com/us/app/notekeeper/id381190368?mt=8"&gt;Notekeeper&lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;&lt;/table&gt;</description><link>http://weblog.highorderbit.com/post/6145383478</link><guid>http://weblog.highorderbit.com/post/6145383478</guid><pubDate>Fri, 03 Jun 2011 10:47:30 -0600</pubDate><category>products</category><category>announcements</category></item><item><title>Introducing Chirpy 2.0!</title><description>&lt;p&gt;About a year ago we released a wonderful iPhone app called &lt;a href="http://chirpyapp.com"&gt;Chirpy&lt;/a&gt;. Chirpy does one thing really well: it provides a way to quickly send and receive Twitter direct messages, without the other 2,000+ features of a full-fledged Twitter client getting in your way. It&amp;#8217;s also great if you&amp;#8217;re looking for a way to cut down on your monthly SMS usage, or need a simple and fast messaging app to keep in touch with friends and family overseas. And because it has incredibly fast push notifications, it&amp;#8217;ll let you know when you get a new message right away, even when the app isn&amp;#8217;t running.&lt;/p&gt;

&lt;center&gt;

&lt;div style="margin-bottom:10px;"&gt;
&lt;a href="http://itunes.apple.com/us/app/chirpy/id370400161?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm2s5zMFcf1qfjldc.png"/&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;/center&gt;

&lt;p&gt;Since we released the first version of Chirpy, we&amp;#8217;ve gotten a lot of feature requests from people requesting things like updated graphics for the iPhone 4&amp;#8217;s high-resolution Retina Display, the ability to delete messages, and a way to share photos privately, among others.&lt;/p&gt;

&lt;p&gt;Today I&amp;#8217;m extremely excited to announce Chirpy 2.0 that includes all of these features and so much more! Here&amp;#8217;s a screenshot of the new chat screen:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lm2rv8vcYS1qfjldc.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;First, you&amp;#8217;ll notice the app has an entirely new look and feel. We didn&amp;#8217;t just update the existing artwork for the iPhone 4. We have a completely new look to the chat bubbles in conversations (colors that you can configure yourself), and we&amp;#8217;ve added contact pictures to both the &amp;#8220;inbox&amp;#8221; (your list of conversations) and the conversations themselves. If you&amp;#8217;re using an iPhone 4, we&amp;#8217;re using Twitter&amp;#8217;s high-resolution pictures, so they look stunning on a Retina Display. Chirpy also automatically recognizes phone numbers, URLs, addresses, and events within message text. Tapping on them takes the appropriate action (for example, tapping on a phone number calls that number, tapping on an address opens it in Google Maps, and so on). And you can copy-and-paste text from a message.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lm2ry3uFvl1qfjldc.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Photo sharing has gotten a major upgrade with the ability to share photos privately using &lt;a href="http://www.dropbox.com"&gt;Dropbox&lt;/a&gt;. (If you&amp;#8217;ve never used Dropbox before, I strongly suggest you check it out. Accounts are free and it&amp;#8217;s an amazingly useful service that&amp;#8217;s dead simple to use.) In Chirpy, when you attach a photo to a message, the image is uploaded to a Chirpy folder within your public Dropbox folder. Photos within this directory are accessible through a public URL. No one knows this URL except you and the recipient of the message, so only the sender and recipient of the message can see it. Chirpy embeds a thumbnail of the image directly into the message just as it always has. You don&amp;#8217;t even see the ugly URLs in your conversation if you don&amp;#8217;t want, though there&amp;#8217;s an option to always show them if you prefer that.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lm2rwzNp2O1qfjldc.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve also added another extremely common feature request: the ability to delete messages. In Chirpy, this works just like it does in the built-in Messages app, so there should be no learning curve. When you select a bunch of messages, you also have the option of sending them in an email message.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a full bulleted list of the major features in Chirpy 2.0:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;All new chat view with beautiful bubble graphics&lt;/li&gt;
&lt;li&gt;Chat bubble colors are fully customizable&lt;/li&gt;
&lt;li&gt;Profile pictures are displayed in the chat view&lt;/li&gt;
&lt;li&gt;Profile pictures are displayed in the inbox view&lt;/li&gt;
&lt;li&gt;Use Dropbox to share photos privately&lt;/li&gt;
&lt;li&gt;Delete messages&lt;/li&gt;
&lt;li&gt;Email messages&lt;/li&gt;
&lt;li&gt;Search your inbox for messages&lt;/li&gt;
&lt;li&gt;Copy-and-paste messages&lt;/li&gt;
&lt;li&gt;Tap on links, addresses, phone numbers, and dates in conversations to take appropriate actions&lt;/li&gt;
&lt;li&gt;Mark all messages as read with a single tap&lt;/li&gt;
&lt;li&gt;Moved settings into the app. They used to be in the Settings app, which is where Apple wants you to put them, but no one can ever find them there.&lt;/li&gt;
&lt;li&gt;Tons of smaller new features, refinements, and bug fixes.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;With all of this good there is a tiny smidgeon of bad. Twitter recently announced that all third-party apps that want to access direct messages have to make two changes to their software. First, they have to use Twitter&amp;#8217;s web-based log in workflow rather than the old workflow that allowed app developers to collect users&amp;#8217; usernames and passwords directly. Second, apps that access direct messages have to request all users to log in and explicitly grant the app access to their direct messages again, even if they already logged in to the app using the old system in the past.&lt;/p&gt;

&lt;p&gt;This web-based log in is cumbersome within an iPhone app, but not terrible. And the pain is one-time only. Once you add your accounts, you&amp;#8217;re done and never have to think about this process again.&lt;/p&gt;

&lt;p&gt;Chirpy 2.0 is a huge leap forward over the current version. It&amp;#8217;s a free upgrade for current users, and everyone else can &lt;a href="http://itunes.apple.com/us/app/chirpy/id370400161?mt=8"&gt;buy it on the App Store today&lt;/a&gt;!&lt;/p&gt;

&lt;center&gt;

&lt;div style="margin-bottom:10px;"&gt;
&lt;a href="http://itunes.apple.com/us/app/chirpy/id370400161?mt=8"&gt;&lt;img src="http://media.tumblr.com/tumblr_lm2s5zMFcf1qfjldc.png"/&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;/center&gt;</description><link>http://weblog.highorderbit.com/post/6110451525</link><guid>http://weblog.highorderbit.com/post/6110451525</guid><pubDate>Thu, 02 Jun 2011 10:36:47 -0600</pubDate><category>chirpy</category><category>announcements</category><category>products</category></item><item><title>Learning to Leave Vim and Embrace Xcode </title><description>&lt;p&gt;&lt;b&gt;Moving Away from Vim&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m a big believer in the Pragmatic Programmer maxim &lt;a href="http://pragprog.com/the-pragmatic-programmer/extracts/tips" title="The Pragmatic Bookshelf"&gt;&amp;#8220;Use a Single Editor Well&amp;#8221;&lt;/a&gt;. My editor of choice is Vim. &lt;a href="http://www.viemu.com/a-why-vi-vim.html"&gt;Modal editing&lt;/a&gt; lets you do just about everything without leaving the home row. No &lt;a href="http://www.gnu.org/software/emacs/"&gt;carpel-tunnel-inducing key combinations&lt;/a&gt; required.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve spent more effort than I&amp;#8217;d like to admit getting Vim to work in just about every possible text editing environment. I&amp;#8217;m using &lt;a href="http://code.google.com/p/macvim/"&gt;MacVim&lt;/a&gt; and &lt;a href="http://plasticboy.com/markdown-vim-mode/"&gt;Markdown Mode&lt;/a&gt; to write this post. I&amp;#8217;ve used Vi emulators to write &lt;a href="http://ideavim.sourceforge.net/"&gt;Java code&lt;/a&gt; and &lt;a href="http://www.viemu.com/"&gt;C++ code&lt;/a&gt; in various IDEs. I use Vim as my &lt;a href="http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-sheet/"&gt;line editor&lt;/a&gt; in my shell.&lt;/p&gt;

&lt;p&gt;And of course I&amp;#8217;ve taken the time to &lt;a href="http://blog.highorderbit.com/2009/09/02/building-xcode-projects-in-vim-with-rake/"&gt;configure Vim&lt;/a&gt; to support as much of the iOS development cycle as possible. That is until a few months ago, when I ditched Vim cold turkey for iOS development and jumped with both feet into using Xcode full time.&lt;/p&gt;

&lt;p&gt;Why abandon Vim in favor of the (in my opinion) clumsy editing environment of Xcode? I got tired of paying the tax of lugging around an extra tool. Vim is an absolutely phenomenal text editing tool. It&amp;#8217;s a decent build tool, enabling one to walk through build errors fairly easily, as long as they&amp;#8217;re compiler errors and not linker or other problems. Among major development tasks, debugging is the most important that can only be done in Xcode. That reality makes trying to fix a bug while debugging a pain because it&amp;#8217;s hard to start navigating the project and typing code in an environment as different from Vim as Xcode. Interacting with iOS documentation in Vim is a pain, despite the best efforts of some &lt;a href="http://www.vim.org/scripts/script.php?script_id=2674"&gt;useful plugins&lt;/a&gt;. Switching to Xcode to manage these and other extraneous tasks, like editing Core Data models, adding files to a project, or editing build settings, over time became increasingly grating.&lt;/p&gt;

&lt;p&gt;Then I got a piece of advice I found convincing enough to push me over the edge: it&amp;#8217;s better to invest time mastering the standard tool than waste an even greater amount of time trying to work around it. Considering this in the light of the forthcoming Xcode 4, with its even tighter overall integration of the iOS development cycle (integrated Interface Builder, for example), put me over the edge. I switched to Xcode full time and invested effort in making it work better for my workflow.&lt;/p&gt;

&lt;p&gt;The primary focus for my efforts to improve development in Xcode has been in making text editing more efficient.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Customizing the Cocoa Text System&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Most programmers who write code on Mac OS X are familiar with the Cocoa text system&amp;#8217;s set of &lt;a href="http://www.hcs.harvard.edu/~jrus/Site/System%20Bindings.html"&gt;key bindings derived from Emacs&lt;/a&gt;.  If not, here&amp;#8217;s a quick primer. In any native Cocoa text field &amp;#8212; the address bar in Safari or Chrome, a compose window in Mail, or, critically, Xcode&amp;#8217;s text editor &amp;#8212; a subset of Emacs editing commands are available. This includes ctrl-a to go to the beginning of a line (paragraph in OS X terms), ctrl-k to kill a line, ctrl-y to yank (paste) what was last killed, and ctrl-f to move forward one letter.&lt;/p&gt;

&lt;p&gt;(Brief digression: one of the great advantages of Mac OS X is its reliance on the command and option keys to drive most of their key bindings. Windows and Linux rely on the control key. For example, on a Mac, command-a selects all, whereas on Widows control-a selects all. Using command-a allows Macs to support the Emacs binding of control-a to move to the beginning of the line.  Most users will never know or care that this binding exists, but it&amp;#8217;s wonderful for programmers.)&lt;/p&gt;

&lt;p&gt;One more obscure aspect of the Cocoa text editing system that&amp;#8217;s &lt;strong&gt;not&lt;/strong&gt; known to most programmers is that new key mappings can be defined by editing a plist file called &lt;a href="http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html"&gt;~/Library/KeyBindings/DefaultKeyBinding.dict&lt;/a&gt;. By editing this file, you are able to create key bindings inaccessible through the UI.  Once defined, these bindings are available in any native Cocoa text field in any application. It&amp;#8217;s extremely simple to set up once you know the syntax, and the payoff is huge. It&amp;#8217;s the next best thing to having a universal &lt;a href="http://www.corsofamily.net/jcorso/vi/"&gt;vi emulator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Say you want to map ctrl-w to delete one word backwards. Here&amp;#8217;s a snippet of the contents of the &lt;code&gt;DefaultKeyBinding.dict&lt;/code&gt; file:&lt;/p&gt;

&lt;script src="https://gist.github.com/871986.js?file=gistfile1.xml"&gt;&lt;/script&gt;&lt;p&gt;Simple, right?&lt;/p&gt;

&lt;p&gt;While you can find plenty of &lt;a href="http://www.google.com/search?q=defaultkeybinding.dict"&gt;good documentation&lt;/a&gt; on setting up your &lt;code&gt;DefaultKeyBinding.dict&lt;/code&gt; file, there are a couple things I&amp;#8217;d like to point out.&lt;/p&gt;

&lt;p&gt;First, you can map single key bindings to multiple command selectors. For example, I&amp;#8217;ve configured control-shift-k to delete the current line regardless of cursor position. This requires multiple commands to perform, which is accomplished like so:&lt;/p&gt;

&lt;script src="https://gist.github.com/871988.js?file=DefaultKeyBinding.dict"&gt;&lt;/script&gt;&lt;p&gt;This affords amazing flexibility to define your own custom bindings.&lt;/p&gt;

&lt;p&gt;The second feature I&amp;#8217;d like to call attention to is the ability to map commands to multi-stroke key bindings. For example, to map the command ctrl-m ctrl-m to set mark (I strongly suggest you &lt;a href="http://cocoawithlove.com/2009/12/multiple-copy-buffers-cursor-and-tab.html"&gt;read more&lt;/a&gt; about marking and yanking in OS X), add this to your file:&lt;/p&gt;

&lt;script src="https://gist.github.com/871992.js?file=DefaultKeyBinding.dict"&gt;&lt;/script&gt;&lt;p&gt;Rather than devise continually contorted key bindings to support the growing set of commands you&amp;#8217;d like to create, you can use multi-key bindings to effectively provide a namespace for sets of related actions. Here&amp;#8217;s an example set of commands related to marking and yanking. Note that multi-key bindings can be configured to use multiple selectors as well. Thus ctrl-m ctrl-x is configured to cut the text between the cursor and the mark.&lt;/p&gt;

&lt;script src="https://gist.github.com/871998.js?file=DefaultKeyBinding.dict"&gt;&lt;/script&gt;&lt;p&gt;Another advantage to this is that it&amp;#8217;s easy to make bindings mnemonic and therefore easy for me to remember. Even better, they don&amp;#8217;t require contorted gestures requiring the simultaneous typing of three modifier keys to work.&lt;/p&gt;

&lt;p&gt;Investing some time in setting up custom binding has paid off in allowing me to do all of my text editing supported by fairly simple key combinations, none of which require reaching for the arrow keys. I keep my bindings &lt;a href="https://github.com/jad/mac-key-bindings"&gt;on GitHub&lt;/a&gt;, so feel free to borrow from them and suggest improvements.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Custom Key Bindings for Xcode&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Xcode uses the standard Cocoa text view as its text editor (for better or for worse). That means any bindings you&amp;#8217;ve added to your &lt;code&gt;DefaultKeyBinding.dict&lt;/code&gt; file will work just fine in Xcode. But Xcode provdes its own set of text editing selectors that aren&amp;#8217;t available in the stock Cocoa text fields. These include commands for moving a subword backward or forward, or to use the current selection for find. Most of these commands can be configured easily in Xcode&amp;#8217;s user interface for editing key bindings. Xcode 3 even supports multi-key bindings in the user interface (sadly this seems to be missing in the Xcode 4 GM).&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s still useful to add key bindings manually, though. The general idea behind doing so is the same, but the syntax of the plist file is slightly different. The file for Xcode 3 lives in &lt;code&gt;~/Library/Application Support/Xcode/Key Bindings/&lt;/code&gt;, and for Xcode 4 in &lt;code&gt;~/Library/Developer/Xcode/UserData/KeyBindings/&lt;/code&gt;. Its name is the name of the bindings set, and has an extension of &lt;code&gt;.pbxkeys&lt;/code&gt; for Xcode 3 and &lt;code&gt;idekeybindings&lt;/code&gt; for Xcode 4. One binding I use frequently is ctrl-x ctrl-i to find the next occurance of the word under the cursor. This is done by selecting the word under the cursor, using the selection for find, and finding next:&lt;/p&gt;

&lt;script src="https://gist.github.com/872002.js?file=john.idekeybindings"&gt;&lt;/script&gt;&lt;p&gt;Once again, taking the time to invest in a few simple customizations can remove much of the pain out of editing text with Xcode. I won&amp;#8217;t go so far as to say that editing is as efficient as it is in Vim. I will say, though, that editing in Xcode no longer feels like typing with mittens, and I can now reap the benefits of keeping all of my iOS development within the single first-party tool. Feel free to use my bindings for &lt;a href="https://github.com/jad/xcode-key-bindings"&gt;Xcode 3&lt;/a&gt; or &lt;a href="https://github.com/jad/xcode4-key-bindings"&gt;Xcode 4&lt;/a&gt; to get you started.&lt;/p&gt;

&lt;p&gt;As I said at the outset, I went cold turkey from doing all of my editing and building in Vim and everything else in Xcode to now living in Xcode 100% of the time. Overall my life is easier and my development is more efficient. Most important, I&amp;#8217;m spendign less time fighting with my tools and more time writing code.&lt;/p&gt;</description><link>http://weblog.highorderbit.com/post/3901744683</link><guid>http://weblog.highorderbit.com/post/3901744683</guid><pubDate>Wed, 16 Mar 2011 12:00:08 -0600</pubDate></item><item><title>New Home for the High Order Blog</title><description>&lt;p&gt;Welcome to the new home of the High Order Blog. All new content will be posted here, so make sure to update your bookmarks and to point your RSS reader to the &lt;a href="http://weblog.highorderbit.com/rss"&gt;new address&lt;/a&gt;. I&amp;#8217;m going to leave the &lt;a href="http://blog.highorderbit.com"&gt;old blog&lt;/a&gt; up, so old links will continue to work.&lt;/p&gt;

&lt;p&gt;Lots of exciting stuff to come. Stay tuned.&lt;/p&gt;</description><link>http://weblog.highorderbit.com/post/3083687838</link><guid>http://weblog.highorderbit.com/post/3083687838</guid><pubDate>Thu, 03 Feb 2011 00:15:55 -0700</pubDate></item></channel></rss>

