<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Light Year Software &#187; Mac</title>
	<atom:link href="http://lightyearsoftware.com/tag/mac/feed/" rel="self" type="application/rss+xml" />
	<link>http://lightyearsoftware.com</link>
	<description></description>
	<lastBuildDate>Fri, 03 Feb 2012 22:19:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Sold on Homebrew</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F02%2Fsold-on-homebrew%2F&#038;seed_title=Sold+on+Homebrew</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F02%2Fsold-on-homebrew%2F&#038;seed_title=Sold+on+Homebrew#comments</comments>
		<pubDate>Fri, 03 Feb 2012 22:19:00 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Ruby & Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=827</guid>
		<description><![CDATA[I&#8217;ve been a MacPorts user for a very long time, so when I heard about Homebrew, I looked into it, but didn&#8217;t see anything compelling enough to convince me to switch. That changed today. I&#8217;m starting a new Rails project. I want to use Ruby 1.9.3 from the beginning to ease a future upgrade to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a <a href="http://www.macports.org/">MacPorts</a> user for a very long time, so when I heard about <a href="http://mxcl.github.com/homebrew/">Homebrew</a>, I looked into it, but didn&#8217;t see anything compelling enough to convince me to switch. That changed today.<span id="more-827"></span></p>
<p>I&#8217;m starting a new Rails project. I want to use Ruby 1.9.3 from the beginning to ease a future upgrade to Rails 4.0, which will require it. This presented a few issues I had to work through for my development and production environments.</p>
<p>Mac OS X ships with Ruby 1.8.7, but I&#8217;ve been using <a href="https://rvm.beginrescueend.com/">RVM</a> to manage different Ruby versions in development and it&#8217;s worked fine. Debian is my preferred server distribution and the latest stable release includes Ruby 1.9.2-p0.</p>
<p>I&#8217;m not completely comfortable with using RVM in a production environment, and I don&#8217;t want to take on the work of installing my own Ruby entirely by hand, so this led me to look at <a href="https://github.com/sstephenson/rbenv">rbenv</a>, a lightweight alternative to RVM. It seems better suited for use in a production environment. I like to match development to production when possible so there are less things to remember, and so I switched to rbenv on my development machine, as well. Paired with <a href="https://github.com/sstephenson/ruby-build">ruby-build</a>, it gives me the important features I used from RVM (I never made much use of gem sets).</p>
<p>It did not go well.</p>
<pre>
$ rbenv install 1.9.3-p0
$ RBENV_VERSION=1.9.3-p0 gem install bundler rails
$ rbenv rehash
$ RBENV_VERSION=1.9.3-p0 rails new app
...
/Volumes/User/Steve/.rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/net/http.rb:799: [BUG] Segmentation fault
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.3.0]
</pre>
<p>Searching for solutions led me to suspect that this is due to a library version mismatch between the compiled Ruby and a gem. MacPorts can make this more common, because unlike Homebrew, it imposes strict control over dependencies and will install a new version of something (e.g., OpenSSL) even if Mac OS X ships with an older one that would work fine.</p>
<p>Rather than track down the problem library, then figure out how to ask rbenv to link with a different version of it, I decided to try Homebrew.</p>
<p>It worked flawlessly. The error when creating a new Rails project is gone.</p>
<p>What really sealed the deal for me came next. I like PostgreSQL, partly because it supports additional data types that can be very useful. One example is <tt>cube</tt>, which is used by the earthdistance extension to store locations and do fast proximity searches. On MacPorts, installing those &#8220;contrib&#8221; extensions is a <a href="http://lightyearsoftware.com/2010/08/adding-contrib-extensions-to-macports-postgresql/" title="Adding “contrib” Extensions to MacPorts PostgreSQL">manual, clunky process</a>. On Homebrew, all the contrib extensions are already compiled and available.</p>
<p>Sold.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F02%2Fsold-on-homebrew%2F&#038;seed_title=Sold+on+Homebrew/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Non-Rectangular Buttons on iOS</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F01%2Fnon-rectangular-buttons-on-ios%2F&#038;seed_title=Non-Rectangular+Buttons+on+iOS</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F01%2Fnon-rectangular-buttons-on-ios%2F&#038;seed_title=Non-Rectangular+Buttons+on+iOS#comments</comments>
		<pubDate>Tue, 03 Jan 2012 20:35:00 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=700</guid>
		<description><![CDATA[One of the projects I worked on last year was the iOS SDK for Yahoo! Connected TV. Along with the SDK, Yahoo! wanted to ship an example app that demonstrated use of the SDK. Take a look at the screenshot to the right. See anything a little out of the ordinary? Several of the buttons, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://lightyearsoftware.com/wp-content/uploads/2012/01/connectedtv.png"><img class="alignright size-full wp-image-786" title="sample remote from Yahoo! Connected TV iOS SDK" src="http://lightyearsoftware.com/wp-content/uploads/2012/01/connectedtv.png" alt="sample remote from Yahoo! Connected TV iOS SDK" width="220" height="330" /></a>One of the projects I worked on last year was the iOS SDK for <a href="http://connectedtv.yahoo.com/">Yahoo! Connected TV</a>. Along with the SDK, Yahoo! wanted to ship an example app that demonstrated use of the SDK. Take a look at the screenshot to the right. See anything a little out of the ordinary?</p>
<p>Several of the buttons, especially the colored ones along the bottom half of the directional pad, are not rectangular.<span id="more-700"></span></p>
<p><a href="http://lightyearsoftware.com/wp-content/uploads/2012/01/connectedtv-detail.png"><img class="alignleft size-full wp-image-788" title="the frame of the green button, showing how it overlaps the down and rewind buttons" src="http://lightyearsoftware.com/wp-content/uploads/2012/01/connectedtv-detail.png" alt="the frame of the green button, showing how it overlaps the down and rewind buttons" width="203" height="170" /></a>It doesn&#8217;t matter if we&#8217;re developing on the Mac or iOS. Views are rectangular and they either gobble a click/tap or they don&#8217;t. Take a look at the green button. The blue outline shows the frame of the view. It overlaps two other buttons: down and rewind. Especially on iOS, where a fingertip is an imprecise input method, a user will find it very frustrating if a tap on down was instead interpreted as green.</p>
<p>The solution is quite straightforward on iOS: create a subclass of <tt>UIButton</tt> and override <tt>-pointInside:withEvent:</tt>.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> pointInside<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGPoint<span style="color: #002200;">&#41;</span>point withEvent<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIEvent <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">/* Surprisingly, this method is called even when point has a negative
     * component and is obviously outside of self.bounds. */</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>CGRectContainsPoint<span style="color: #002200;">&#40;</span>self.bounds, point<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">/* The point is within our bounds. If a mask exists, check the mask
         * for an allowed tap. If there is no mask, let the superclass
         * (UIButton) do the work. */</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>mask <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">return</span> mask<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>point.y <span style="color: #002200;">*</span> maskWidth <span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>point.x<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>super pointInside<span style="color: #002200;">:</span>point withEvent<span style="color: #002200;">:</span>event<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p><tt>pointInside:withEvent:</tt> is called by <tt>hitTest:withEvent:</tt>, once for each subview. If a subview returns <tt>NO</tt>, then its branch of the hierarchy is ignored. By making <tt>pointInside:withEvent:</tt> sensitive to only the part of the image that is the button, it&#8217;s possible to ignore events for taps on a part that doesn&#8217;t.</p>
<p>The key is building a mask. Here, it is a two dimensional <tt>BOOL</tt> array. If <tt>mask</tt> is not <tt>NULL</tt>, the x and y of the point is used to index into the array and return the value there. If <tt>mask</tt> is <tt>NULL</tt> for any reason, the code simply falls back to the superclass&#8217;s behavior. </p>
<p>One way to build the mask is to look at the alpha channel of the image.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> buildMask
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>mask<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">free</span><span style="color: #002200;">&#40;</span>mask<span style="color: #002200;">&#41;</span>;
        mask <span style="color: #002200;">=</span> <span style="color: #a61390;">NULL</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    CGImageRef image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self imageForState<span style="color: #002200;">:</span>UIControlStateNormal<span style="color: #002200;">&#93;</span>.CGImage;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>image <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    NSUInteger width <span style="color: #002200;">=</span> CGImageGetWidth<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    NSUInteger height <span style="color: #002200;">=</span> CGImageGetHeight<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    uint32_t <span style="color: #002200;">*</span>pixels <span style="color: #002200;">=</span> <span style="color: #a61390;">malloc</span><span style="color: #002200;">&#40;</span>width <span style="color: #002200;">*</span> height <span style="color: #002200;">*</span> <span style="color: #2400d9;">4</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>pixels <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">/* Provided that memory for the temporary 32-bit pixel array was
         * available, draw the CGImage into that memory. */</span>
&nbsp;
        CGColorSpaceRef colorSpaceRef <span style="color: #002200;">=</span> CGColorSpaceCreateDeviceRGB<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
        CGContextRef context <span style="color: #002200;">=</span> CGBitmapContextCreate<span style="color: #002200;">&#40;</span>pixels, width, height,
                                                     CGImageGetBitsPerComponent<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>,
                                                     width <span style="color: #002200;">*</span> <span style="color: #2400d9;">4</span>, colorSpaceRef,
                                                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Host<span style="color: #002200;">&#41;</span>;
&nbsp;
        CGContextSetBlendMode<span style="color: #002200;">&#40;</span>context, kCGBlendModeCopy<span style="color: #002200;">&#41;</span>;
        CGContextDrawImage<span style="color: #002200;">&#40;</span>context, CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, width, height<span style="color: #002200;">&#41;</span>, image<span style="color: #002200;">&#41;</span>;
        CGContextRelease<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
        CGColorSpaceRelease<span style="color: #002200;">&#40;</span>colorSpaceRef<span style="color: #002200;">&#41;</span>;
&nbsp;
        mask <span style="color: #002200;">=</span> <span style="color: #a61390;">malloc</span><span style="color: #002200;">&#40;</span>width <span style="color: #002200;">*</span> height <span style="color: #002200;">*</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
        maskWidth <span style="color: #002200;">=</span> width;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>mask <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger y <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; y &lt; height; <span style="color: #002200;">++</span>y<span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger x <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; x &lt; width; <span style="color: #002200;">++</span>x<span style="color: #002200;">&#41;</span>
                <span style="color: #002200;">&#123;</span>
                    <span style="color: #11740a; font-style: italic;">/* RGBA: high 24 bits are color, low 8 bits are alpha.
                     * Less than 50% alpha is the untapped part of the image. */</span>
                    mask<span style="color: #002200;">&#91;</span>y <span style="color: #002200;">*</span> width <span style="color: #002200;">+</span> x<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>pixels<span style="color: #002200;">&#91;</span>y <span style="color: #002200;">*</span> width <span style="color: #002200;">+</span> x<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;</span> 0xFF<span style="color: #002200;">&#41;</span> &gt; <span style="color: #2400d9;">128</span>;
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to allocate memory, will fall back to UIButton behavior.&quot;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #a61390;">free</span><span style="color: #002200;">&#40;</span>pixels<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to allocate memory, will fall back to UIButton behavior.&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image forState<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIControlState<span style="color: #002200;">&#41;</span>state
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super setImage<span style="color: #002200;">:</span>image forState<span style="color: #002200;">:</span>state<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self buildMask<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The subclass overrides <tt>setImage:forState:</tt> so that when the image is set or changed, the mask is regenerated. To use a non-rectangular button within Interface Builder, we need to also override <tt>initWithCoder:</tt>.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithCoder<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSCoder</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>coder
<span style="color: #002200;">&#123;</span>
    self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super initWithCoder<span style="color: #002200;">:</span>coder<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>self<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self buildMask<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>If you don&#8217;t want to use the alpha channel, another option is to provide an explicit mask image. Masks are monochrome bitmaps, where white indicates the visible area. Building the <tt>mask</tt> array from a mask image is very similar to using the alpha channel. The only difference is what part of the pixel data is analyzed.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setMaskImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>maskImage
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>mask<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">free</span><span style="color: #002200;">&#40;</span>mask<span style="color: #002200;">&#41;</span>;
        mask <span style="color: #002200;">=</span> <span style="color: #a61390;">NULL</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>maskImage <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    CGImageRef image <span style="color: #002200;">=</span> maskImage.CGImage;
    NSUInteger width <span style="color: #002200;">=</span> CGImageGetWidth<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    NSUInteger height <span style="color: #002200;">=</span> CGImageGetHeight<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    uint32_t <span style="color: #002200;">*</span>pixels <span style="color: #002200;">=</span> <span style="color: #a61390;">malloc</span><span style="color: #002200;">&#40;</span>width <span style="color: #002200;">*</span> height <span style="color: #002200;">*</span> <span style="color: #2400d9;">4</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>pixels <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">/* Provided that memory for the temporary 32-bit pixel array was
         * available, draw the CGImage into that memory. */</span>
&nbsp;
        CGColorSpaceRef colorSpaceRef <span style="color: #002200;">=</span> CGColorSpaceCreateDeviceRGB<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
        CGContextRef context <span style="color: #002200;">=</span> CGBitmapContextCreate<span style="color: #002200;">&#40;</span>pixels, width, height,
                                                     CGImageGetBitsPerComponent<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>,
                                                     width <span style="color: #002200;">*</span> <span style="color: #2400d9;">4</span>, colorSpaceRef,
                                                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Host<span style="color: #002200;">&#41;</span>;
&nbsp;
        CGContextSetBlendMode<span style="color: #002200;">&#40;</span>context, kCGBlendModeCopy<span style="color: #002200;">&#41;</span>;
        CGContextDrawImage<span style="color: #002200;">&#40;</span>context, CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, width, height<span style="color: #002200;">&#41;</span>, image<span style="color: #002200;">&#41;</span>;
        CGContextRelease<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
        CGColorSpaceRelease<span style="color: #002200;">&#40;</span>colorSpaceRef<span style="color: #002200;">&#41;</span>;
&nbsp;
        mask <span style="color: #002200;">=</span> <span style="color: #a61390;">malloc</span><span style="color: #002200;">&#40;</span>width <span style="color: #002200;">*</span> height <span style="color: #002200;">*</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
        maskWidth <span style="color: #002200;">=</span> width;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>mask <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger y <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; y &lt; height; <span style="color: #002200;">++</span>y<span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger x <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; x &lt; width; <span style="color: #002200;">++</span>x<span style="color: #002200;">&#41;</span>
                <span style="color: #002200;">&#123;</span>
                    <span style="color: #11740a; font-style: italic;">/* RGBA: high 24 bits are color. Anything other than black
                     * is tappable. */</span>
                    mask<span style="color: #002200;">&#91;</span>y <span style="color: #002200;">*</span> width <span style="color: #002200;">+</span> x<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>pixels<span style="color: #002200;">&#91;</span>y <span style="color: #002200;">*</span> width <span style="color: #002200;">+</span> x<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;</span> 0xFFFFFF00<span style="color: #002200;">&#41;</span> <span style="color: #002200;">!=</span> <span style="color: #2400d9;">0</span>;
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to allocate memory, will fall back to UIButton behavior.&quot;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        <span style="color: #a61390;">free</span><span style="color: #002200;">&#40;</span>pixels<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to allocate memory, will fall back to UIButton behavior.&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2012%2F01%2Fnon-rectangular-buttons-on-ios%2F&#038;seed_title=Non-Rectangular+Buttons+on+iOS/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit Testing Cocoa with MacRuby</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F09%2Funit-testing-cocoa-with-macruby%2F&#038;seed_title=Unit+Testing+Cocoa+with+MacRuby</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F09%2Funit-testing-cocoa-with-macruby%2F&#038;seed_title=Unit+Testing+Cocoa+with+MacRuby#comments</comments>
		<pubDate>Thu, 29 Sep 2011 15:43:05 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby & Rails]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=727</guid>
		<description><![CDATA[I spend most of my development time split between Rails and iOS. Each offers a rich API that makes building projects much more productive and enjoyable. There is one place, however, that Ruby clobbers Objective-C: testing. It&#8217;s not that Objective-C doesn&#8217;t have test frameworks. There are several: OCUnit (bundled with Xcode), GHUnit, Cedar and Kiwi. [...]]]></description>
			<content:encoded><![CDATA[<p>I spend most of my development time split between Rails and iOS. Each offers a rich API that makes building projects much more productive and enjoyable. There is one place, however, that Ruby clobbers Objective-C: testing.<span id="more-727"></span></p>
<p>It&#8217;s not that Objective-C doesn&#8217;t have test frameworks. There are several: <a href="http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/ios_development_workflow/135-Unit_Testing_Applications/unit_testing_applications.html">OCUnit</a> (bundled with Xcode), <a href="https://github.com/gabriel/gh-unit">GHUnit</a>, <a href="https://github.com/pivotal/cedar">Cedar</a> and <a href="http://www.kiwi-lib.info/">Kiwi</a>. Cedar and Kiwi use blocks to get close to an RSpec-like syntax, but there&#8217;s only so far it can go. Objective-C can&#8217;t match Ruby when creating a DSL, even with preprocessor abuse.</p>
<p>Fortunately, there is a way to write tests in Ruby and run them against Objective-C code: <a href="http://www.macruby.org/">MacRuby</a>. MacRuby is an implementation of Ruby 1.9 that compiles Ruby to LLVM bytecode and has full access to Objective-C frameworks. You can write full Mac desktop applications with it, but for this post I&#8217;ll simply use it to write test specs with RSpec for testing Objective-C classes.</p>
<p>In this post, I&#8217;ll walk you through how to install MacRuby, RSpec and how to set up your Cocoa (Mac or iOS) project to unit test with RSpec. These tests are analogous to model specs in Rails. We&#8217;ll be testing classes in isolation, not trying to recreate the Cocoa environment in order to test window or view controllers, etc.</p>
<p>A big caveat for iOS developers: MacRuby loads Objective-C code from a framework, but iOS targets don&#8217;t support building frameworks. What this means is that you don&#8217;t have access to the <tt>UI*</tt> classes in the code under test. This limits what you can test. Pure model classes (those without any external dependencies) will be fine. Theoretically, it should be possible to find the simulator frameworks and link against those, but I&#8217;ve been unsuccessful thus far. <a href="http://chameleonproject.org/">Chameleon</a> might help if you want to dig into this further.</p>
<p>With that out of the way, let&#8217;s get started. If you haven&#8217;t already, download and install MacRuby. This places the <tt>macruby</tt> binary and other Ruby tools you&#8217;re familiar with (<tt>irb</tt>, <tt>gem</tt>, <tt>rake</tt>) in <tt>/usr/local/bin</tt>, with <tt>mac</tt> prefixes.</p>
<p>Then, install RSpec 2.5 (at present, there are <a href="https://github.com/rspec/rspec-core/issues/461">problems running specs with 2.6</a>).</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">$ sudo macgem install --bindir /usr/local/bin --format-executable rspec -v '~&gt;2.5.0'</pre></div></div>

<p><tt>--bindir</tt> ensures the <tt>rspec</tt> script doesn&#8217;t overwrite one that might already exist in <tt>/usr/bin</tt>, and <tt>--format-executable</tt> adds the <tt>mac</tt> prefix to it, so it matches the other MacRuby-provided scripts.</p>
<p>In Xcode, open your project and create a new target (File -> New Target). Use the Cocoa Framework template, found under Mac OS X, Framework &amp; Library. Call it whatever you like. I used &#8220;Specs&#8221;. Do not use Automatic Reference Counting. MacRuby, like MRI Ruby, is garbage collected and will use the Objective-C garbage collector. If your project uses ARC, that&#8217;s OK. <tt>retain</tt>, <tt>release</tt> and <tt>autorelease</tt> are no-ops under GC, and nothing changes if the calls to them are missing in the first place. Include Unit Tests should also be unchecked.</p>
<p>You must adjust some build settings for the new target. Under Apple LLVM Compiler &#8211; Language, find the settings for Objective-C Automatic Reference Counting and ensure it is set to NO. Just below that, set Objective-C Garbage Collection to Supported.</p>
<p><img class="size-full wp-image-729 aligncenter" title="compiler settings for ARC and GC" src="http://lightyearsoftware.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-23-at-11.47.39-AM.png" alt="" width="438" height="53" /></p>
<p>Go to the target build phases, and add the <tt>.m</tt> files you wish to test to the compile sources phase. As you add files to your project later, be sure to check the boxes for both your main target and the Specs target if you want to test the new code.</p>
<p>Finally, you need to configure the schemes for the new target. In the build scheme, check the run box. In the run scheme, choose <tt>/usr/local/bin/macruby</tt> as the executable to test.</p>
<p><img class="size-full wp-image-730 aligncenter" title="run scheme info configuration" src="http://lightyearsoftware.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-23-at-11.53.56-AM.png" alt="" width="424" height="209" /></p>
<p>Set up the arguments to pass to the executable when it runs as follows:</p>
<p><img class="size-full wp-image-731 aligncenter" title="run scheme arguments configuration" src="http://lightyearsoftware.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-23-at-11.54.10-AM.png" alt="" width="526" height="312" /></p>
<p>Choose your framework as the base for expansions. You&#8217;ll pass two arguments to the program: the path to the RSpec wrapper and the directory containing the specs.</p>
<p>You might wonder why we&#8217;re using MacRuby as the executable to test instead of RSpec directly. If you try to use RSpec, Xcode won&#8217;t recognize it as a 64-bit executable and will refuse to run it under the debugger. It will work, but you must also choose &#8220;debugger: none&#8221; and give up your breakpoints, etc.</p>
<p>With this new target you get a new top-level group in your project. Xcode has also created Specs.h and Specs.m, which we don&#8217;t need. You should delete them.</p>
<p>Create a new file in this group called <tt>spec_helper.rb</tt> and paste this in:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">framework <span style="color:#996600;">'Specs'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Requires supporting ruby files with custom matchers and macros, etc,</span>
<span style="color:#008000; font-style:italic;"># in spec/support/ and its subdirectories.</span>
<span style="color:#CC00FF; font-weight:bold;">Dir</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;#{ENV['SRCROOT']}/Specs/support/**/*.rb&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">require</span> f<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
RSpec.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#008000; font-style:italic;"># == Mock Framework</span>
  <span style="color:#008000; font-style:italic;">#</span>
  <span style="color:#008000; font-style:italic;"># If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:</span>
  <span style="color:#008000; font-style:italic;">#</span>
  <span style="color:#008000; font-style:italic;"># config.mock_with :mocha</span>
  <span style="color:#008000; font-style:italic;"># config.mock_with :flexmock</span>
  <span style="color:#008000; font-style:italic;"># config.mock_with :rr</span>
  config.<span style="color:#9900CC;">mock_with</span> <span style="color:#ff3333; font-weight:bold;">:spec</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>At this point, you should be able to choose your new target from the scheme picker in the toolbar and run. We haven&#8217;t created any specs yet, so you should see this:</p>
<pre>
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug  8 20:32:45 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys004
[Switching to process 1636 thread 0x0]
No examples were matched. Perhaps {:if=>#&lt;Proc:0x4007553a0 (lambda)>, :unless=>#&lt;Proc:0x400795b60 (lambda)>} is excluding everything?

Finished in 0.0331 seconds
0 examples, 0 failures
Program ended with exit code: 0
</pre>
<p>You may not see any output. You can use ⌘7 and look at the most recent log or use this <a href="http://twitter.com/pilky/status/109737034633060352">tip from Martin Pilkington</a> to create a new window for output. I find this much less intrusive than allowing Xcode to constantly pop up the debugging panes in my editor windows.</p>
<p>Let&#8217;s create a simple spec file. Assuming you added a <tt>.m</tt> file that implements a class called <tt>Foo</tt>, create a new file in your Specs group called <tt>foo_spec.rb</tt>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;#{ENV['SRCROOT']}/Specs/spec_helper&quot;</span>
&nbsp;
describe Foo <span style="color:#9966CC; font-weight:bold;">do</span>
  it <span style="color:#006600; font-weight:bold;">&#123;</span> should be_an_instance_of<span style="color:#006600; font-weight:bold;">&#40;</span>Foo<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Run again and you should see this:</p>
<pre>
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug  8 20:32:45 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys004
[Switching to process 1796 thread 0x0]
.

Finished in 0.40422 seconds
1 example, 0 failures
Program ended with exit code: 0
</pre>
<p>It works! Now try adding breakpoints, mocking and stubbing objects, etc. You have all the features of RSpec available to you.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F09%2Funit-testing-cocoa-with-macruby%2F&#038;seed_title=Unit+Testing+Cocoa+with+MacRuby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Slides from Cocoa Networking Talk</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F08%2Fslides-from-cocoa-networking-talk%2F&#038;seed_title=Slides+from+Cocoa+Networking+Talk</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F08%2Fslides-from-cocoa-networking-talk%2F&#038;seed_title=Slides+from+Cocoa+Networking+Talk#comments</comments>
		<pubDate>Mon, 15 Aug 2011 14:21:22 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[speaking]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=723</guid>
		<description><![CDATA[I have posted the slides from my talk on networking with Cocoa at CocoaConf. For those that attended: thank you! It was great meeting so many new people and having the opportunity to present. One common suggestion for improvement from attendees was for demos. These are always tricky with networking topics, because you never know [...]]]></description>
			<content:encoded><![CDATA[<p>I have posted the slides from <a href="/slides/CocoaNetworking.pdf" title="Cocoa Networking slides">my talk on networking with Cocoa</a> at <a href="http://cocoaconf.com/" title="CocoaConf">CocoaConf</a>. For those that attended: thank you! It was great meeting so many new people and having the opportunity to present.</p>
<p>One common suggestion for improvement from attendees was for demos. These are always tricky with networking topics, because you never know how good the Wi-Fi will be at a conference. When I give this talk in the future, I think I will split it into two, build some demos, and bring a second laptop with a cross-over cable.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F08%2Fslides-from-cocoa-networking-talk%2F&#038;seed_title=Slides+from+Cocoa+Networking+Talk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Your Own Private WWDC 2011</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F07%2Fyour-own-private-wwdc-2011%2F&#038;seed_title=Your+Own+Private+WWDC+2011</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F07%2Fyour-own-private-wwdc-2011%2F&#038;seed_title=Your+Own+Private+WWDC+2011#comments</comments>
		<pubDate>Fri, 01 Jul 2011 15:24:57 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=702</guid>
		<description><![CDATA[Now that Apple has released the complete set of WWDC 2011 videos to registered developers, those of us who couldn&#8217;t make it to the conference have the opportunity to hear about all the new, shiny stuff coming in Mac OS X 10.7 and iOS 5. With 109 sessions to choose from, newcomers may not know [...]]]></description>
			<content:encoded><![CDATA[<p>Now that Apple has released the complete set of <a href="http://developer.apple.com/videos/wwdc/2011/">WWDC 2011 videos</a> to registered developers, those of us who couldn&#8217;t make it to the conference have the opportunity to hear about all the new, shiny stuff coming in Mac OS X 10.7 and iOS 5.<span id="more-702"></span></p>
<p>With 109 sessions to choose from, newcomers may not know where to start. This guide is intended to help you get started.</p>
<p><a href="http://www.apple.com/apple-events/wwdc-2011/"><strong>The Keynote</strong></a>: the only WWDC session not under NDA, this is where all the public news was announced. If for some reason you haven&#8217;t watched it yet, it&#8217;s worth watching, although it is a bit long and by now you&#8217;ve probably heard about everything.</p>
<p>Since everything else is under NDA, I can&#8217;t discuss specifics about the content of sessions.</p>
<p>Start with the <strong>Apple Platforms Kickoff</strong>. Where the keynote is truly for the press, this session is for developers.</p>
<p>Whether your focus is on Mac OS X or iOS, you&#8217;ll be using Xcode, so move on to <strong>Session 300: Developer Tools Kickoff</strong>. You&#8217;ll learn about the new tools and features coming in future versions of Xcode.</p>
<p>The final kickoff session is <strong>Session 400: Graphics, Media, and Games Kickoff</strong>. I found this session to be less focused on new stuff and more a general overview of the available frameworks and tools, though the demo at the end is impressive. There is a bit about Game Center and AV Foundation if you&#8217;re interested in these frameworks.</p>
<p>Trivia: in previous years, these sessions used the &#8220;State of the Union&#8221; moniker.</p>
<p>Where to next? That depends on what you want to do. Many sessions include pointers to others covering specific topics, so be sure to watch for those to find more information about areas that interest you.</p>
<h2>If you&#8217;re a Mac OS X developer&#8230;</h2>
<p>If you have an app in the Mac App Store or plan to ship one in the future, start with <strong>Session 203: Introducing App Sandbox</strong> and <strong>Session 204: App Sandbox and the Mac App Store</strong>. There are new submission requirements coming with 10.7 that are more important than anything else.</p>
<p>Follow that up with <strong>Session 101: What&#8217;s New in Cocoa</strong>. This is the high-level session to learn about the new stuff for developers in 10.7. Don&#8217;t miss <strong>Session 323: Introducing Automatic Reference Counting</strong> so you can (mostly) stop thinking about manual memory management.</p>
<p><strong>Session 127: Design Patterns to Simplify Mac Accessibility</strong> is James Dempsey&#8217;s annual talk that includes a song. Even if you don&#8217;t think you care about accessibility (hint: you should), his talk is great and the song is a funny distillation of the topic.</p>
<h2>If you&#8217;re an iOS developer&#8230;</h2>
<p>Start with <strong>Session 100: What&#8217;s New in Cocoa Touch</strong>, then <strong>Session 323: Introducing Automatic Reference Counting</strong>, followed by <strong>Session 309: Introducing Interface Builder Storyboarding</strong> and <strong>Session 102: Implementing UIViewController Containment</strong>. Follow the suggestions for related sessions depending on your interests and needs.</p>
<h2>App Design</h2>
<p>Excellent design will set your app apart from the crowd. There are two sessions covering UI and UX topics: <strong>Session 110: Designing User Interfaces for iOS and Mac OS X Apps</strong> and <strong>Session 105: Polishing Your App</strong>, the latter of which includes non-visual polish such as responsiveness and performance, a user experience issue.</p>
<h2>Security and Performance</h2>
<p>You should care about the security of your app and how well it performs. <strong>Session 202: Security Overview</strong> discusses attack vectors and options for addressing them. <strong>Session 310: What&#8217;s New in Instruments</strong> will point you in the right direction for performance analysis and tuning, while <strong>Session 312: iOS Performance and Power Optimization with Instruments</strong> and <strong>Session 318: iOS Performance in Depth</strong> teaches practical techniques for diagnosing and fixing problems for iOS apps.</p>
<p>Releasing these videos for free is a great service to the Apple developer community. There is value in almost every session, and the huge advantage we have in watching them now is we can check out topics we might not have made time for if attending the conference in person. Skip ahead or stop a video if it isn&#8217;t holding your attention.</p>
<p>My recommendations here are a starting point. Apple&#8217;s platforms are growing and getting better every year. Explore new things; you never know when you might learn something relevant to an existing project. Watch a session about a topic you think you know well. With such a rich set of frameworks, there are often little tricks to learn that mean you can rewrite some old code to be clearer or perform better.</p>
<p>Is there a particularly good session I haven&#8217;t mentioned? Mention it in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F07%2Fyour-own-private-wwdc-2011%2F&#038;seed_title=Your+Own+Private+WWDC+2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CocoaConf</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F06%2Fcocoaconf%2F&#038;seed_title=CocoaConf</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F06%2Fcocoaconf%2F&#038;seed_title=CocoaConf#comments</comments>
		<pubDate>Fri, 03 Jun 2011 15:49:47 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[speaking]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=675</guid>
		<description><![CDATA[CocoaConf is a new developer-focused conference for Mac OS X and iOS being held August 12-13 in Columbus, OH. I am presenting a session on networking with Cocoa. It will cover the various APIs available to Mac OS X and iOS developers from Apple and third-parties, as well as touch on issues unique to using [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cocoaconf.com/">CocoaConf</a> is a new developer-focused conference for Mac OS X and iOS being held August 12-13 in Columbus, OH. I am presenting a session on networking with Cocoa. It will cover the various APIs available to Mac OS X and iOS developers from Apple and third-parties, as well as touch on issues unique to using the network on a mobile platform.</p>
<p>Early registration opened today and you can get a conference pass for 50% off.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F06%2Fcocoaconf%2F&#038;seed_title=CocoaConf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL 5.5 on Mac OS X</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F02%2Fmysql-5-5-on-mac-os-x%2F&#038;seed_title=MySQL+5.5+on+Mac+OS+X</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F02%2Fmysql-5-5-on-mac-os-x%2F&#038;seed_title=MySQL+5.5+on+Mac+OS+X#comments</comments>
		<pubDate>Fri, 25 Feb 2011 16:22:52 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ruby & Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/?p=643</guid>
		<description><![CDATA[If you&#8217;re (re)building a development workstation on Mac OS X, you may have decided to use the latest MySQL 5.5 packages from mysql.com. Unfortunately, that means you probably have seen (or will soon see) two problems. The first is this: dlopen(/Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle, 9): Library not loaded: libmysqlclient.16.dylib Referenced from: /Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle Reason: image not found - /Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re (re)building a development workstation on Mac OS X, you may have decided to use the latest MySQL 5.5 packages from mysql.com. Unfortunately, that means you probably have seen (or will soon see) two problems.<span id="more-643"></span> The first is this:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">dlopen(/Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle, 9): Library not loaded: libmysqlclient.16.dylib
Referenced from: /Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle
Reason: image not found - /Library/Ruby/Gems/1.8/gems/mysql2-0.2.6/lib/mysql2/mysql2.bundle</pre></div></div>

<p>That example is from the mysql2 gem, but the same problem exists with the older mysql gem. The problem is that the libmysqlclient shared library in the MySQL 5.5 package does not specify a full path to the library. When something links with it, such as the MySQL gem, it won&#8217;t be able to find the library at runtime.</p>
<p>There are two ways to fix this.</p>
<ol>
<li>
<p>The easy way: modify <tt>DYLD_LIBRARY_PATH</tt> in your <tt>.bash_profile</tt> (or equivalent if you use another shell). The advantage to this method is that it fixes it once for anything that links with the MySQL client libraries going forward. Add:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">DYLD_LIBRARY_PATH=&quot;/usr/local/mysql/lib:$DYLD_LIBRARY_PATH&quot;</pre></div></div>

</li>
<li>
<p>The hard, do-it-again-someday way: modify the <tt>.bundle</tt> files within the gem to use an absolute path to the MySQL client library. The fix is lost when reinstalling the gem or updating to a new version and must be reapplied. Change to your gem&#8217;s root, somewhere like <tt>/Library/Ruby/Gems/1.8/gems/mysql-2.8.1</tt> or <tt>.../mysql2-0.2.6</tt>, or even both. There are two <tt>.bundle</tt> files within the gem (under <tt>lib</tt> and <tt>ext</tt>) that you must run the following command on.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo install_name_tool -change libmysqlclient.16.dylib /usr/local/mysql/lib/libmysqlclient.16.dylib mysql_api.bundle</pre></div></div>

</li>
</ol>
<p>The second problem with the MySQL 5.5 packages is in the MySQLStartupItem and preference pane. Neither work to start or stop the server.</p>
<ol>
<li>
<p>The ownership of the StartupItem files is wrong. OS X complains with</p>
<blockquote><p>&#8220;/Library/StartupItems/MySQLCOM” has not been started because it does not have the proper security settings.</p></blockquote>
<p>To fix that, run:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo chown -R root:wheel /Library/StartupItems/MySQLCOM</pre></div></div>

</li>
<li>
<p><tt>basedir</tt> and <tt>datadir</tt> are not set in <tt>/usr/local/mysql/support-files/mysql.server</tt>, which breaks the preference pane. Edit that file with superuser privileges (<tt>sudo mate</tt> or vi, joe, &#8230;) and set them:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">basedir=/usr/local/mysql
datadir=/usr/local/mysql/data</pre></div></div>

</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F02%2Fmysql-5-5-on-mac-os-x%2F&#038;seed_title=MySQL+5.5+on+Mac+OS+X/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Apple Isn&#8217;t Earning Their 30%</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F01%2Fapple-isnt-earning-their-30%2F&#038;seed_title=Apple+Isn%26%238217%3Bt+Earning+Their+30%25</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F01%2Fapple-isnt-earning-their-30%2F&#038;seed_title=Apple+Isn%26%238217%3Bt+Earning+Their+30%25#comments</comments>
		<pubDate>Tue, 01 Feb 2011 03:21:22 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://new.lightyearsoftware.com/?p=504</guid>
		<description><![CDATA[Much has been said over the last 2½ years about the App Store and places where Apple is failing third-party developers. Many things have been fixed, but unfortunately, many more have been neglected or only partially addressed. On January 22, 2011, the App Store surpassed 10 billion downloads. Let&#8217;s assume 1% of those are paid [...]]]></description>
			<content:encoded><![CDATA[<p>Much has been said over the last 2½ years about the App Store and places where Apple is failing third-party developers. Many things have been fixed, but unfortunately, many more have been neglected or only partially addressed. On January 22, 2011, the App Store surpassed 10 billion downloads. Let&#8217;s assume 1% of those are paid and Apple only takes the minimum 29¢ for each one. That&#8217;s still $29 million. Apple needs to do a lot more to earn their 30% cut.<span id="more-504"></span></p>
<p>There are problems on both the selling and buying sides of the store. Much more has been said about the problems for sellers, but I&#8217;ll run down the list anyway.</p>
<p><strong>No analytics:</strong> Small developers don&#8217;t have unlimited budgets, so the money we spend on marketing must be spent wisely. This is impossible without feedback. We don&#8217;t know how many people are looking at our apps or where they came from. That makes it impossible to measure an ad&#8217;s effectiveness. AdMob offers a way to close this loop for ads run on their network, but it requires sending them complete sales data and a marker that they can use to build a detailed picture of the apps users are buying and running.</p>
<p><strong>Little price flexibility:</strong> We can&#8217;t offer coupons or specials to loyal customers or upgrade pricing. Historically, major version upgrades are a big part of a small developer&#8217;s revenue. On the App Stores, new and recurring customers are treated the same.</p>
<p><strong>No trials:</strong> Probably the #1 reason apps are so cheap on the iOS App Store is because it&#8217;s impossible for customers to try before they buy.</p>
<p><strong>No contact with customers:</strong> We don&#8217;t know who our customers are and can&#8217;t contact them for any reason.</p>
<p><strong>Reviews are a toxic, one-sided conversation:</strong> Customers can leave scathing reviews filled with untrue statements, and we&#8217;re powerless to respond. It&#8217;s allowing customers to picket our storefront.</p>
<p><strong>Reviews and no control over release timing:</strong> Developers can (and are) rejected by Apple&#8217;s review team for ridiculous reasons. Even when an app is accepted, review can still take two weeks or more. For updates, this means a known and fixed bug remains in the field and causing problems long after it should.</p>
<p><strong>Greatly reduced cash flow:</strong> Developers are paid by Apple at the end of each month for the previous month&#8217;s sales. At best, that&#8217;s a 30 day delay before receiving the cash. At worst, 60 days. For small developers, that makes paying employees and vendors much harder.</p>
<p>The problems don&#8217;t end there, though. As successful as the App Store has been, if the buying experience were improved, it could be much more so. Here&#8217;s an experiment for you to try.</p>
<p>Imagine you&#8217;re unhappy with your current weather app, whatever it may be. Go find the &#8220;best&#8221; alternative.</p>
<p>I tried doing this and quickly gave up because the buying experience when you don&#8217;t already know exactly what you want is awful.</p>
<p><strong>Search is limited:</strong> search looks at only app titles and keywords. This is undoubtably because unscrupulous developers try to game the system, but it also means customers must rely on developers choosing meaningful names and keywords. It&#8217;s led to borderline spammy app titles. The result is that search queries are short and return either nothing or lots of results.</p>
<p><strong>No way to sort or filter results:</strong> literally, no way. You can only browse the results, in the order Apple returns them, page by page. Off the top of my head, some obvious sorting options that would be useful: by rating (both all time and current version) and by price. Useful filters: price tiers, age, and category.</p>
<p><strong>No useful ways to sort when browsing categories:</strong> The only choices when browsing a category are by name or release date.</p>
<p>The App Store has over 300,000 apps. Imagine trying to shop at Amazon if you couldn&#8217;t sort or filter. For the developer, what this essentially means is that you won&#8217;t make any money unless you &#8220;win the lottery:&#8221; Apple decides to feature your app and/or you make it into the top seller lists. Features are also of limited benefit: the category-specific What&#8217;s New and What&#8217;s Hot lists aren&#8217;t available on the device, which I&#8217;m willing to bet is where the vast majority of people shop.</p>
<p><strong>No trials</strong> and <strong>no upgrade pricing:</strong> There is obviously overlap here. As a customer, I&#8217;m less willing to buy a more expensive app unless I have confidence it works. Similarly, I&#8217;m less willing to spend a bit more than I&#8217;d like for an app if I know the next major version will cost me just as much or more (on the desktop, I can justify it since the upgrade is often discounted).</p>
<p>I don&#8217;t expect that Apple will fix any of these problems. 10 billion downloads in 2½ years is a remarkable achievement. Apple is a hardware company; while the App Store is certainly profitable, as long as hardware sales stay strong, that&#8217;s what they really care about.</p>
<p>All I can do as a small developer is learn from past mistakes and not repeat them in the future. For me, that means no more mass-market, 99¢ apps and likely no more advertising. My future products will focus on niche markets, solving real problems instead of filling a few minutes of a bored customer&#8217;s time. These are the people that should be willing to tolerate the App Store&#8217;s limitations and eventually find my app, likely even searching Google on their computer and not exclusively shopping from the device.</p>
<p><strong>Update Feb. 4:</strong> <a href="http://www.macrumors.com/2011/02/04/ipad-app-store-gains-search-filters-install-buttons-for-previously-purchased-apps/">MacRumors</a> reports that on the iPad, the App Store now offers filtering of search results. I hope something similar comes to the iPhone and iPod touch.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2011%2F01%2Fapple-isnt-earning-their-30%2F&#038;seed_title=Apple+Isn%26%238217%3Bt+Earning+Their+30%25/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Automatic Git Revision Stamping for App Store Projects</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F11%2Fautomatic-git-revision-stamping-for-app-store-projects%2F&#038;seed_title=Automatic+Git+Revision+Stamping+for+App+Store+Projects</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F11%2Fautomatic-git-revision-stamping-for-app-store-projects%2F&#038;seed_title=Automatic+Git+Revision+Stamping+for+App+Store+Projects#comments</comments>
		<pubDate>Tue, 02 Nov 2010 15:57:42 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=310</guid>
		<description><![CDATA[Following up on my post about automatic Subversion revision stamping, here is a modified script for use with Git-based projects. I&#8217;ve been moving toward Git for more of my work, for mostly two reasons. The first is that Subversion uses &#8220;@&#8221; to denote a specific revision of a file, which makes adding images for the [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on my post about <a href="http://lightyearsoftware.com/blog/2010/05/automatic-subversion-revision-stamping-for-iphone-projects/">automatic Subversion revision stamping</a>, here is a modified script for use with Git-based projects.<span id="more-310"></span></p>
<p>I&#8217;ve been moving toward Git for more of my work, for mostly two reasons. The first is that Subversion uses &#8220;@&#8221; to denote a specific revision of a file, which makes adding images for the Retina Display annoying because they use &#8220;@2x&#8221; in the file name. The second is that integrating third-party source into a project is more work than it should be because Subversion litters the tree with <tt>.svn</tt> directories. I can&#8217;t simply delete the old third-party source and drop in the new files, because Subversion loses its state. Yes, I could <tt>svn rm</tt>, then <tt>svn add</tt>, but that grows the repository unnecessarily and I lose the ability to diff the source and see what actually changed.</p>
<p>Git does not use a numeric repository version, however, and a simple SHA1 hash is unsuitable for use as the third component of a bundle version because it can include the letters a-f. I took the simplest way out and use a file (<tt>build-counter</tt>) with a number in it, incremented for every Ad Hoc and App Store build, but not for Debug or Release. This file is created if it does not exist and automatically committed.</p>
<p>As with my Subversion script, if any local modifications are detected during an Ad Hoc or App Store build, it will fail.</p>
<p>Since it&#8217;s likely that Apple will enforce the same format restrictions on Mac App Store apps, this script can also be used in those projects.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Xcode auto-versioning script for Git by Steve Madsen.</span>
<span style="color:#008000; font-style:italic;"># Adapted from Subversion script by Axel Andersson.</span>
&nbsp;
build_counter_file = <span style="color:#996600;">'build-counter'</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;#{$0}: Must be run from Xcode&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'BUILT_PRODUCTS_DIR'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> development?
  ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'BUILD_STYLE'</span><span style="color:#006600; font-weight:bold;">&#93;</span> !~ <span style="color:#006600; font-weight:bold;">/</span>Ad Hoc<span style="color:#006600; font-weight:bold;">|</span>App Store<span style="color:#006600; font-weight:bold;">/</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> local_modifications?
  <span style="color:#996600;">`git ls-files -m`</span> != <span style="color:#996600;">&quot;&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
build_counter = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>build_counter_file<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span> <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#006666;">0</span>
<span style="color:#9966CC; font-weight:bold;">unless</span> development?
  <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;#{$0}: local modifications present for a production build!&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> local_modifications?
&nbsp;
  build_counter <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
  <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>build_counter_file, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#CC0066; font-weight:bold;">printf</span> <span style="color:#996600;">&quot;%d&quot;</span>, build_counter <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC0066; font-weight:bold;">system</span> <span style="color:#996600;">&quot;git commit -m 'increment build counter' #{build_counter_file}&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;#{$0}: Git commit of #{build_counter_file} failed: #{$?.exitstatus}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
info = <span style="color:#996600;">&quot;#{ENV['BUILT_PRODUCTS_DIR']}/#{ENV['WRAPPER_NAME']}/Info.plist&quot;</span>
info_xml = <span style="color:#996600;">`plutil -convert xml1 '#{info}' -o -`</span>
<span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;#{$0}: reading Info.plist failed: #{$?.exitstatus}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> $?.<span style="color:#9900CC;">success</span>?
&nbsp;
info_xml.<span style="color:#CC0066; font-weight:bold;">gsub!</span> <span style="color:#006600; font-weight:bold;">%</span>r<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>\t <span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span>CFBundleVersion\n<span style="color:#006600; font-weight:bold;">&#91;</span>\t <span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span>\d<span style="color:#006600; font-weight:bold;">+</span>\.\d<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#006600; font-weight:bold;">*</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#996600;">&quot;<span style="color:#000099;">\\</span>1.#{build_counter}<span style="color:#000099;">\\</span>2&quot;</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">popen</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;plutil -convert binary1 - -o '#{info}'&quot;</span>, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>plutil<span style="color:#006600; font-weight:bold;">|</span> plutil <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; info_xml <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;#{$0}: writing Info.plist failed: #{$?.exitstatus}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> $?.<span style="color:#9900CC;">success</span>?</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F11%2Fautomatic-git-revision-stamping-for-app-store-projects%2F&#038;seed_title=Automatic+Git+Revision+Stamping+for+App+Store+Projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Option-Click to Reposition Cursor in Terminal</title>
		<link>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F10%2Foption-click-to-reposition-cursor-in-terminal%2F&#038;seed_title=Option-Click+to+Reposition+Cursor+in+Terminal</link>
		<comments>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F10%2Foption-click-to-reposition-cursor-in-terminal%2F&#038;seed_title=Option-Click+to+Reposition+Cursor+in+Terminal#comments</comments>
		<pubDate>Fri, 08 Oct 2010 01:43:07 +0000</pubDate>
		<dc:creator>Steve Madsen</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=307</guid>
		<description><![CDATA[I found this on SuperUser today and just have to share it. In Terminal, you can reposition the cursor on a line by option-clicking where you want it to go. Credit where due. It doesn&#8217;t happen every day, but certainly a few times a week: I end up with a monster command, spanning two full [...]]]></description>
			<content:encoded><![CDATA[<p>I found this on <a href="http://superuser.com/">SuperUser</a> today and just have to share it.</p>
<p>In Terminal, you can reposition the cursor on a line by option-clicking where you want it to go. <a href="http://superuser.com/questions/52483/terminal-tips-and-tricks-for-mac-os-x/167640#167640">Credit where due.</a></p>
<p>It doesn&#8217;t happen every day, but certainly a few times a week: I end up with a monster command, spanning two full 100 character wide lines or more. Inevitably, there&#8217;s an error in there in the middle, and I sit waiting, holding down left-arrow to fix it and try again.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/feeder/?FeederAction=clicked&#038;feed=Articles+%28RSS2%29&#038;seed=http%3A%2F%2Flightyearsoftware.com%2F2010%2F10%2Foption-click-to-reposition-cursor-in-terminal%2F&#038;seed_title=Option-Click+to+Reposition+Cursor+in+Terminal/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.007 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-04 08:21:34 -->

