<?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>Carpé Cocoa &#187; iPhone Development</title>
	<atom:link href="http://carpe-cocoa.com/category/iphone-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://carpe-cocoa.com</link>
	<description>My journey into iPhone development</description>
	<lastBuildDate>Tue, 24 Nov 2009 21:03:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Detecting when Bluetooth is disabled with GKSession</title>
		<link>http://carpe-cocoa.com/2009-07-29/detecting-when-bluetooth-is-disabled-with-gksession/</link>
		<comments>http://carpe-cocoa.com/2009-07-29/detecting-when-bluetooth-is-disabled-with-gksession/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 21:47:45 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[GameKit]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=304</guid>
		<description><![CDATA[Edit: As noted in the comments, this technique no longer works in iPhone OS 3.1.
If you are writing an iPhone GameKit app without using GKPeerPickerController (as I did in PhotoBeamer), you need to detect when Bluetooth is disabled and ask the user to turn it on in the settings app. Apple doesn&#8217;t provide a way [...]]]></description>
			<content:encoded><![CDATA[<p><em>Edit: As noted in the comments, this technique no longer works in iPhone OS 3.1.</em></p>
<p>If you are writing an iPhone GameKit app without using <code>GKPeerPickerController</code> (as I did in <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=321814330&amp;mt=8">PhotoBeamer</a>), you need to detect when Bluetooth is disabled and ask the user to turn it on in the settings app. Apple doesn&#8217;t provide a way for a developer to enable Bluetooth other than through <code>GKPeerPickerController</code>.</p>
<p>This is pretty easy to do. First, create your <code>GKSession</code> and set it to be available:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">    session <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>GKSession alloc<span style="color: #002200;">&#93;</span> initWithSessionID<span style="color: #002200;">:</span>kMyAppSessionID
                                       displayName<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                                       sessionMode<span style="color: #002200;">:</span>GKSessionModeClient<span style="color: #002200;">&#93;</span>;
    session.delegate <span style="color: #002200;">=</span> self;
    <span style="color: #002200;">&#91;</span>session setDataReceiveHandler<span style="color: #002200;">:</span>self withContext<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    session.available <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;</pre></div></div>

<p>Next, set up your <code lang="objc">- (void)session:(GKSession *)session didFailWithError:(NSError *)error</code> delegate method to detect when Bluetooth is not available and alert the user:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// GKSessionErrorDomain causes link error (rdar://problem/7014349)</span>
<span style="color: #6e371a;">#if 0</span>
<span style="color: #6e371a;">#define kGKSessionErrorDomain GKSessionErrorDomain</span>
<span style="color: #6e371a;">#else</span>
<span style="color: #6e371a;">#define kGKSessionErrorDomain @&quot;com.apple.gamekit.GKSessionErrorDomain&quot;</span>
<span style="color: #6e371a;">#endif</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>session<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>GKSession <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>session didFailWithError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>error <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>error domain<span style="color: #002200;">&#93;</span> isEqual<span style="color: #002200;">:</span>kGKSessionErrorDomain<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp;
        <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>error code<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> GKSessionCannotEnableError<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;">// Bluetooth disabled, prompt the user to turn it on</span>
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Some other error, get the description from the NSError object</span>
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// destroy the GKSession and clean up</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The <code lang="objc">GKSessionErrorDomain</code> symbol causes a link error for me, so I&#8217;m temporarily using the constant string instead. When Apple fixes the SDK, I&#8217;ll change that <code lang="objc">#if 0</code> to use the official symbolic name.</p>
<p>Note that this error will sometimes occur on a reconnection attempt even when Bluetooth is enabled, presumably because the old session is still partially active.</p>
<p>It would be nice to have a more user-friendly way to turn on Bluetooth without leaving the app and without using the full <code lang="objc">GKPeerPickerController</code> UI. I&#8217;ve filed a bug report (rdar://problem/7061502) asking for this functionality. You should <a title="Apple Bug Reporter" href="https://bugreport.apple.com/" target="_blank">file one too</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-07-29/detecting-when-bluetooth-is-disabled-with-gksession/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>PhotoBeamer Available in the App Store</title>
		<link>http://carpe-cocoa.com/2009-07-14/photobeamer-available-in-the-app-store/</link>
		<comments>http://carpe-cocoa.com/2009-07-14/photobeamer-available-in-the-app-store/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 16:06:31 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[appMobi]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=242</guid>
		<description><![CDATA[A little over a month ago, the appMobi team was sitting outside around a table at our favorite bar/restaurant, enjoying the warm summer weather and a cold drink. We had just finished our last meeting before I headed off to WWDC, and we were sharing pictures on our iPhones by passing them around the table. [...]]]></description>
			<content:encoded><![CDATA[<p>A little over a month ago, the appMobi team was sitting outside around a table at our favorite bar/restaurant, enjoying the warm summer weather and a cold drink. We had just finished our last meeting before I headed off to WWDC, and we were sharing pictures on our iPhones by passing them around the table. That was when we realized &#8220;there should be an app for <em>this</em>!&#8221;</p>
<p>Sure, there are apps that let you upload images to Facebook, Flickr, and all sorts of other places&#8230;. Sure, you can email a picture, and with iPhone OS 3.0 coming soon even MMS one (assuming you&#8217;re not in the US and don&#8217;t care about quality). There are even apps that let you share photos on the spot, phone-to-phone, but only if you are all on the same WiFi network.</p>
<p>We knew that 3.0 would be out soon, possibly as soon as WWDC. We also knew that 3.0 had peer-to-peer Bluetooth networking support through the new GameKit framework. We decided this was a perfect opportunity to take advantage of the new OS.</p>
<p>I went home and got some sleep (long day and Crown don&#8217;t make for productive programming), then dived right into GameKit first thing in the morning. By lunch time I was able to share small images reliably, but clearly needed a lot of UI and networking polish. We knew we wouldn&#8217;t be the only ones with this idea, and that the quality of the app would be more important than being the first ones to market.</p>
<p>I spent the rest of the week polishing the prototype, and by the time I left for San Francisco had the core user interface pretty solid: translucent autohiding toolbars, a zooming and scrolling image view very much like the native Photos app, support for viewers coming and going mid-session, and more.</p>
<p>During the keynote at WWDC Apple announced that the 3.0 gold master was available immediately to developers. I updated from the Beta I was running and immediately found bugs in my apps. Not so much in PhotoBeamer, but in SpinSlide, which was already in the store with paying customers. I had to put PhotoBeamer aside and work on fixing the bugs in SpinSlide as quickly as possible, while attending 8+ hours of sessions and nearly as many parties through the week.</p>
<p>Once I got back from WWDC I was able to finish up the bug fixes and internationalization work on SpinSlide (now available in Spanish and Japanese!) and get back to work on PhotoBeamer. I updated the networking code to send arbitrary size images reliably, added a camera button to allow taking pictures right in the app, and continued with the visual polish, adding activity spinners and a status view with separate progress bars for each client and a multi-line status area to ensure the user has a chance to read messages as they come up. I created a free version called BeamCatcher and fought through some issues with my build scripts, and added the ability for the clients to save images to their Photo Album, but only if the sender allows.</p>
<p>A few beta test sessions using multiple devices at once uncovered some more bugs that were addressed, and the arrival of the 3GS showed some more room for improvement in both the networking and image display code, thanks to the larger images. Most importantly, I discovered how to detect when Bluetooth is not enabled without using the built-in peer picker controller, which doesn&#8217;t fit well with the PhotoBeamer app flow.</p>
<p>After all that, and an unusually long review at Apple (likely due to the massive influx of new and updated apps around 3.0), both <a title="See PhotoBeamer in the App Store" href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=321814330&amp;mt=8" target="_blank">PhotoBeamer</a> and <a title="See BeamCatcher in the App Store" href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=321815121&amp;mt=8" target="_blank">BeamCatcher</a> went live June 12th. Get PhotoBeamer to share your pictures. If your friends won&#8217;t spring for the full app, they can download BeamCatcher to view for free.</p>
<p><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Main.jpg" title="PhotoBeamer can send or receive images" rel="lightbox[242]"><img class="size-thumbnail wp-image-243 alignnone" title="PhotoBeamer can send or receive images" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Main-100x150.jpg" alt="PhotoBeamer Main" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-1.jpg" title="Sender decides if clients can save the images" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-244" title="Sender decides if clients can save the images" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-1-100x150.jpg" alt="Sender decides if clients can save the shared images" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-2.jpg" title="Sender decides if client can connect" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-245" title="Sender decides if client can connect" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-2-100x150.jpg" alt="Sender is prompted when a client tries to connect" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-3.jpg" title="Progress is shown for each client" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-246" title="Progress is shown for each client" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-3-100x150.jpg" alt="Progress is shown for each client" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-4.jpg" title="View in portrait or landscape mode" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-247" title="View in portrait or landscape mode" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/PhotoBeamer-Extra-4-150x100.jpg" alt="View in portrait or landscape mode" width="150" height="100" /></a></p>
<p><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Main.jpg" title="BeamCatcher is receive-only" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-248" title="BeamCatcher is receive-only" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Main-100x150.jpg" alt="BeamCatcher is receive-only" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-1.jpg" title="Looking for PhotoBeamers nearby" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-249" title="Looking for PhotoBeamers nearby" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-1-100x150.jpg" alt="Looking for PhotoBeamers nearby" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-2.jpg" title="BeamCatcher receiving the initial image" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-250" title="BeamCatcher receiving the initial image" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-2-100x150.jpg" alt="BeamCatcher receiving the initial image" width="100" height="150" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-3.jpg" title="Image received - save button is now active" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-251" title="Image received - save button is now active" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-3-150x100.jpg" alt="Image received - save button is now active" width="150" height="100" /></a><a href="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-4.jpg" title="After a few seconds the UI slides out allowing an unobstructed view" rel="lightbox[242]"><img class="alignnone size-thumbnail wp-image-252" title="After a few seconds the UI slides out allowing an unobstructed view" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/BeamCatcher-Extra-4-150x100.jpg" alt="After a few seconds the UI slides out allowing an unobstructed view" width="150" height="100" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-07-14/photobeamer-available-in-the-app-store/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>What&#8217;s New in iPhone OS 3.0, A Developer&#8217;s Perspective</title>
		<link>http://carpe-cocoa.com/2009-06-19/whats-new-in-iphone-os-3-0-a-developers-perspective/</link>
		<comments>http://carpe-cocoa.com/2009-06-19/whats-new-in-iphone-os-3-0-a-developers-perspective/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 22:28:45 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=231</guid>
		<description><![CDATA[WWDC 2009 ended a week ago, the new iPhone 3G S is out, and iPhone OS 3.0 has been available for a couple of days now, so I think it&#8217;s finally OK to talk publicly about the 3.0 SDK (after all, you can go get it from Apple for free now).
Last night I gave a [...]]]></description>
			<content:encoded><![CDATA[<p>WWDC 2009 ended a week ago, the new iPhone 3G S is out, and iPhone OS 3.0 has been available for a couple of days now, so I think it&#8217;s finally OK to talk publicly about the 3.0 SDK (after all, you can go get it from <a title="Apple iPhone Developer Portal" href="http://developer.apple.com/iphone" target="_blank">Apple</a> for free now).</p>
<p>Last night I gave a talk at the <a title="Philadelphia Area Mac and iPhone Programming Group" href="http://phillycocoa.org/" target="_blank">Philly CocoaHeads</a> meeting in an attempt to cover the 1000 or so new APIs in over a dozen functional areas in under an hour. I&#8217;m sharing the slides here for all, whether you were able to make it last night or not. We had some great discussions, which unfortunately are not in the slides, but hopefully these will help give you an idea of what is newly possible in iPhone OS, and where to look for more details.</p>
<p><a href="http://carpe-cocoa.com/wp-content/uploads/2009/06/CocoaHeads-June-2009.pptx">What&#8217;s New in iPhone OS 3.0, Philly CocoaHeads June 2009 (pptx, 552kB)</a></p>
<p><a href="http://carpe-cocoa.com/wp-content/uploads/2009/06/CocoaHeads-June-2009-Minimal.pdf">What&#8217;s New in iPhone OS 3.0, Philly CocoaHeads June 2009 (pdf, 366kB)</a></p>
<p>I&#8217;d love to hear your thoughts on the new APIs and how you plan to make use of them in your apps.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-06-19/whats-new-in-iphone-os-3-0-a-developers-perspective/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title></title>
		<link>http://carpe-cocoa.com/2009-06-19/hidden-elephant-software-%c2%bb-targeting-iphone-2-x-on-snow-leopard-with-xcode-3-2/</link>
		<comments>http://carpe-cocoa.com/2009-06-19/hidden-elephant-software-%c2%bb-targeting-iphone-2-x-on-snow-leopard-with-xcode-3-2/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 18:46:28 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=229</guid>
		<description><![CDATA[Serban Porumbescu, whom I met last week at WWDC, posted instructions for targeting iPhone OS 2.x from XCode 3.2.
There&#8217;s not much to add, so I&#8217;m just posting to add it to my Google-powered memory.
]]></description>
			<content:encoded><![CDATA[<p><a title="@serban on Twiter" href="http://twitter.com/serban" target="_blank">Serban Porumbescu</a>, whom I met last week at WWDC, posted instructions for <a title="Hidden Elephant Software - Targeting iPhone 2.x on Snow Leopard with Xcode 3.2" href="http://hiddenelephant.com/blog/2009/06/12/targeting-iphone-2x-on-snow-leopard-with-xcode-32/" target="_blank">targeting iPhone OS 2.x from XCode 3.2</a>.</p>
<p>There&#8217;s not much to add, so I&#8217;m just posting to add it to my Google-powered memory.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-06-19/hidden-elephant-software-%c2%bb-targeting-iphone-2-x-on-snow-leopard-with-xcode-3-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SpinSlide is Live!</title>
		<link>http://carpe-cocoa.com/2009-05-28/spinslide-is-live/</link>
		<comments>http://carpe-cocoa.com/2009-05-28/spinslide-is-live/#comments</comments>
		<pubDate>Fri, 29 May 2009 01:26:40 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[appMobi]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=221</guid>
		<description><![CDATA[SpinSlide is now live! The best damn slide tile puzzle ever!
Watch a video demo, read my previous post about it, or just go buy it!

]]></description>
			<content:encoded><![CDATA[<p><a title="SpinSlide on the AppStore" href="itms://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=317323388&amp;mt=8&amp;s=143441" target="_blank">SpinSlide</a> is now live! The best damn slide tile puzzle ever!</p>
<p>Watch a <a title="SpinSlide Demo Video" href="http://www.youtube.com/watch?v=DdxUK9O88FE" target="_blank">video demo</a>, read my <a title="First App Submission" href="http://carpe-cocoa.com/2009-05-20/first-app-submission/" target="_self">previous post</a> about it, or just <a title="SpinSlide on the AppStore" href="itms://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=317323388&amp;mt=8&amp;s=143441" target="_blank">go buy it!</a></p>
<p><object width="480" height="385" data="http://www.youtube-nocookie.com/v/DdxUK9O88FE&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x5d1719&amp;color2=0xcd311b" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube-nocookie.com/v/DdxUK9O88FE&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x5d1719&amp;color2=0xcd311b" /><param name="allowfullscreen" value="true" /></object></p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-28/spinslide-is-live/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Application Packaging</title>
		<link>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/</link>
		<comments>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/#comments</comments>
		<pubDate>Mon, 25 May 2009 03:33:02 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=176</guid>
		<description><![CDATA[When developing for the iPhone it&#8217;s often necessary to build the application in a form that can be easily installed by collaborators and testers. For ease of installation, the app should be distributed as a .ipa (iPhone Application) file. Unfortunately, XCode does not include a way to do this, so I wrote a bash script [...]]]></description>
			<content:encoded><![CDATA[<p>When developing for the iPhone it&#8217;s often necessary to build the application in a form that can be easily installed by collaborators and testers. For ease of installation, the app should be distributed as a .ipa (iPhone Application) file. Unfortunately, XCode does not include a way to do this, so I wrote a bash script to automate the process.</p>
<p>Additionally, in any build that leaves the developer&#8217;s desk it is especially important to include version information so that bug reports can be traced back to the correct version of the source, and to ensure that any distributed version can be located in the version control system. I use <a title="Git - Fast Version Control" href="http://git-scm.com/" target="_blank">git</a> for source control (installed with <a title="The MacPorts Project -- Available Ports" href="http://www.macports.org/ports.php?by=name&amp;substr=git" target="_blank">MacPorts</a>), though the script should be easily adaptible to CVS or SVN.</p>
<p>The goals for this script were:</p>
<ul>
<li>Automatically tag the project with a unique build number before each build.</li>
<li>Build all supported configurations with a single command. Sometimes compiler errors or warnings are only revealed with certain preprocessor flags or optimization settings.</li>
<li>Ensure any build created for distribution is cleanly committed to version control and tagged.</li>
<li>Name tags so that they can be easily correlated to user-visible version information.</li>
</ul>
<p><span id="more-176"></span></p>
<h4>Preliminaries</h4>
<p>Before we get into <a href="#the_script">the script</a>, a bit of groundwork is needed in the XCode project.</p>
<h5>Build Configurations</h5>
<p>By default, XCode includes two configurations in a new project: Debug and Release. I add a third configuration, Distribution, created by copying the Release configuration, but signed with my distributions certificate instead of the development certificate. This allows me to test using the same build settings that will be used for the submitted app.</p>
<p>I also set a couple of preprocessor flags based on the build configuration. The Debug configuration sets <code>DEVELOPMENT_BUILD=1</code> and <code>DEBUG_BUILD=1</code>, while the Release build just sets <code>DEVELOPMENT_BUILD=1</code>. These flags are used for several purposes, including conditional logging, but in the context of this article they are used just for version string generation.</p>
<p>The versioning tool discussed in the next session also requires a build variable. Search for the <code>CURRENT_PROJECT_VERSION</code> key and set its value to <code>1</code>.</p>
<h5>Apple&#8217;s Versioning Tool</h5>
<p>First, we need to take a little side trip into Apple&#8217;s built-in versioning support. XCode includes <code>agvtool</code>, which with a bit of setup can be used to satisfy our versioning requirements. The first step is to separate the &#8220;marketing version&#8221; from the build version. Both components are stored in the Info.plist file, though a new XCode project only includes the build version key.</p>
<table border="0">
<tbody>
<tr>
<th>Field</th>
<th>Key</th>
<th>agvtool use</th>
<th>Description</th>
</tr>
<tr>
<td>Bundle Version</td>
<td><code>CFBundleVersion</code></td>
<td>(Build) Version</td>
<td>Monotonically increasing integer</td>
</tr>
<tr>
<td>Bundle versions string, short</td>
<td><code>CFBundleShortVersionString</code></td>
<td>Marketing Version</td>
<td>Published version number (e.g. 1.1)</td>
</tr>
</tbody>
</table>
<p>I set the marketing version to the version I plan to specify in iTunesConnect when the app is submitted. The build version is simply set to 1 initially and incremented with each build thereafter (this should match the <code>CURRENT_PROJECT_VERSION</code> build variable).</p>
<h5>Displaying the Version</h5>
<p>In the About view controller&#8217;s <code>viewDidLoad</code> method I include the following:</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>viewDidLoad <span style="color: #002200;">&#123;</span>
   <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>versionString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span>
                        NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Version: %@%@ (%@)&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Version string format&quot;</span><span style="color: #002200;">&#41;</span>,
                        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> objectForInfoDictionaryKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CFBundleShortVersionString&quot;</span><span style="color: #002200;">&#93;</span>,
<span style="color: #6e371a;">#if DEBUG_BUILD</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; Debug&quot;</span>,
<span style="color: #6e371a;">#elif DEVELOPMENT_BUILD</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; Beta&quot;</span>,
<span style="color: #6e371a;">#else</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span>,
<span style="color: #6e371a;">#endif</span>
                        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> objectForInfoDictionaryKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>kCFBundleVersionKey<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#91;</span>versionLabel setText<span style="color: #002200;">:</span>versionString<span style="color: #002200;">&#93;</span>;
   <span style="color: #11740a; font-style: italic;">// Additional initialization</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This provides enough information to determine the build and configuration from any copy of the app. Actually, the marketing version isn&#8217;t even needed, but it allows the user to compare with the information in iTunes.<br />
<a name="the_script"></a></p>
<h3><a name="the_script"></a></h3>
<p>The remainder of this article breaks down the script, section by section. You can <a href="/utils/iPhone/build/build-1.1.sh">download the script</a> (<em>updated July 14, 2009</em>) and use or adapt it to your own projects. The script is under a BSD license.</p>
<p>The description below details the <a href="/utils/iPhone/build/build-1.0.sh">1.0 version</a> of the script.</p>
<h4>Helper Functions</h4>
<p>The first section of the script defines a few helper functions.</p>
<p>The <code>die</code> function simply prints its arguments to <code>stderr</code> and exits.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">die<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;$*&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>The <code>usage</code> function prints its args (if any) followed by a usage message and exits.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">usage<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;$@&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;usage: build [-n] [config...]&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;    -n : do not update build number or commit to git&quot;</span><span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$xcodeconfigs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>    Known configs:&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot; %s&quot;</span> <span style="color: #007800;">$xcodeconfigs</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>Default action is to build all configs<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;This does not appear to be a valid project directory!&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">3</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>The usage message is:</p>
<pre>usage: build [-n] [config...]
    -n : do not update build number or commit to git

    Known configs: Debug Release Distribute

Default action is to build all configs</pre>
<h4>Defaults and Known Configurations</h4>
<p>By default, the script will run agvtool and the git operations, and build all configs in the project.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">nocommit</span>=<span style="color: #000000;">0</span>
<span style="color: #007800;">configs</span>=</pre></div></div>

<p>The list of known configurations is determined by filtering the output of <code>xcodebuild -list</code> with <code>sed</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># all known configurations</span>
<span style="color: #007800;">xcodeconfigs</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>xcodebuild <span style="color: #660033;">-list</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'
		/Build Configurations:/,/^[[:space:]]*$/	!d
		/Build Configurations/				d
		/^[[:space:]]*$/				d
		s/[[:space:]]*\([^[:space:]]*\).*/\1/
	'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>The output of <code>xcodebuild -list</code> looks like:</p>
<pre>$ xcodebuild -list
Information about project "SpinSlide":
    Targets:
        SpinSlide (Active)

    Build Configurations:
        Debug (Active)
        Release
        Distribute

    If no build configuration is specified "Release" is used.</pre>
<p>The four-line <code>sed</code> script first deletes all lines except those between <code>Build Configurations:</code> and the first blank line. The second and third lines delete the <code>Bould Configurations</code> line and the blank line, respectively. Finally, each line is replaced by just the first word on that line.</p>
<p>Next the script checks for an empty list of configurations, which can occur if there is no project bundle in the current directory.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$xcodeconfigs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #666666; font-style: italic;"># no project bundle?</span>
	usage;
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Argument Processing</h4>
<p>Command line arguments are processed in a loop. The only supported flag is &#8216;<code>-n</code>&#8216;, which suppresses <code>avgtool</code> and <code>git</code> operations. All non-flag arguments are assumed to be build configuration names, and are checked against the list of known configurations generated in the last section before being added to the list of configurations to build.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$*&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span>
	<span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #000000; font-weight: bold;">in</span>
		-n<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">nocommit</span>=<span style="color: #000000;">1</span> ; <span style="color: #7a0874; font-weight: bold;">shift</span> <span style="color: #000000; font-weight: bold;">;;</span>
		-<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> usage <span style="color: #000000; font-weight: bold;">;;</span>
		<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$xcodeconfigs</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-wq</span> <span style="color: #ff0000;">&quot;$1&quot;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
				<span style="color: #007800;">configs</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$configs</span> $1&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span>
			<span style="color: #000000; font-weight: bold;">else</span>
				usage <span style="color: #ff0000;">&quot;Invalid config '$1'&quot;</span>
			<span style="color: #000000; font-weight: bold;">fi</span>
			<span style="color: #000000; font-weight: bold;">;;</span>
	<span style="color: #000000; font-weight: bold;">esac</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<p>If no configurations were specified on the command line, all known configurations are built.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># default to building all configs</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$configs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #007800;">configs</span>=<span style="color: #007800;">$xcodeconfigs</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Check for Modified Files</h4>
<p>The next step is to check for modified files. If modified files exist and <code>-n</code> was not specified, the script will exit with an error. If <code>-n</code> was specified the script continues after setting the <code>isdirty</code> flag.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000000; font-weight: bold;">!</span> git status <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-q</span> <span style="color: #ff0000;">'nothing to commit (working directory clean)'</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #666666; font-style: italic;"># if committing the directory must be clean at first</span>
		git status
		die <span style="color: #ff0000;">&quot;directory is dirty&quot;</span>
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #666666; font-style: italic;"># development build, just remember that it was dirty</span>
		<span style="color: #007800;">isdirty</span>=<span style="color: #000000;">1</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">else</span>
	<span style="color: #007800;">isdirty</span>=<span style="color: #000000;">0</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>This step is <code>git</code>-specific, and must be adapted if you are using a different VCS.</p>
<h4>Versioning</h4>
<p>The next step handles all of the versioning and source control operations.</p>
<p>The steps required depend on the command line options used.</p>
<h5>Tagged Builds</h5>
<p>First, we handle the case where the <code>-n</code> flag was not specified. The first step is to use <code>agvtool</code> to determine the marketing version. This will not be changed when the build number is incremented. Checking the marketing version first lets us verify that the project is set up properly before making changes.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #666666; font-style: italic;"># read out the marketing version</span>
	<span style="color: #666666; font-style: italic;"># do this separate from the cut so we can check the exit code</span>
	<span style="color: #007800;">mvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>agvtool mvers -terse<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #660033;">-o</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		die <span style="color: #ff0000;">&quot;No marketing version found&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-q</span> = ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">mvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> <span style="color: #660033;">-f</span> <span style="color: #000000;">2</span> <span style="color: #660033;">-d</span> =<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>The output of <code>agvtool</code> looks like:</p>
<pre>"SpinSlide.xcodeproj/../Info.plist"=1.0</pre>
<p>The <code>cut</code> command is used to extract the field after the <code>=</code> sign.</p>
<p>After this point, the environment has been fully verified, so we can go ahead and increment the build version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># going to commit, bump the version number</span>
	agvtool bump <span style="color: #660033;">-all</span></pre></div></div>

<p>Now we extract the (newly incremented) build version&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #007800;">bvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>agvtool vers -terse<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #660033;">-o</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$bvers</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		die <span style="color: #ff0000;">&quot;No build version found&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>&#8230; and combine the marketing version and build numbers into a human-readable string and a tag identifier, which has the spaces replace by underscores.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># read out the build version, must exist if the marketing version does</span>
	<span style="color: #007800;">fullvers</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span> build <span style="color: #007800;">$bvers</span>&quot;</span>
	<span style="color: #007800;">tag</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tr</span> <span style="color: #ff0000;">' '</span> _<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Finally, we commit the changed .plist and tag the new version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># commit the changed version and tag it</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Committing &quot;</span><span style="color: #007800;">$fullvers</span><span style="color: #ff0000;">&quot; with tag <span style="color: #007800;">$tag</span>&quot;</span>
	git ci <span style="color: #660033;">-a</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Set build version '<span style="color: #007800;">$fullvers</span>'&quot;</span> <span style="color: #660033;">-n</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">'commit failed'</span>
	git tag <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tag</span>&quot;</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span></pre></div></div>

<h5>Untagged Builds</h5>
<p>Untagged builds are much simpler. The SHA1 of the current version is used as the tag. If the source directory is dirty, the current date and time is added to make a unique identifier.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">else</span>
	<span style="color: #666666; font-style: italic;"># not committing, use the SHA1 as the version</span>
	<span style="color: #007800;">fullvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>git rev-parse HEAD <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># if it's dirty, append the date, time, and timezone</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$isdirty</span>&quot;</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">fullvers</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>+ <span style="color: #007800;">$(date +%F\ %T\ %Z)</span>&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Build Prep</h4>
<p>To ensure the build matches the source, we delete the <code>build</code> directory and the <code>Payload</code> directory (the former is used by XCode, the latter by this script).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># clean up old builds so that everything is built from scratch</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> build
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> Payload
<span style="color: #007800;">all</span>=</pre></div></div>

<h4>Build and Package</h4>
<p>Next we loop over the requested configurations, building and packaging each one.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># build and package each requested config</span>
<span style="color: #000000; font-weight: bold;">for</span> config <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$configs</span> ; <span style="color: #000000; font-weight: bold;">do</span></pre></div></div>

<p>The build is performed with the <code>xcodebuild</code> utility, supplied with XCode. A failed build stops the script.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	xcodebuild <span style="color: #660033;">-alltargets</span> <span style="color: #660033;">-parallelizeTargets</span> <span style="color: #660033;">-configuration</span> <span style="color: #007800;">$config</span> build <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Build failed&quot;</span></pre></div></div>

<p>Build output is stored in a tree named for the build type (tagged or untagged), version, and XCode build configuration:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># packaged output goes in Releases if tagged, Development otherwise</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">basedir</span>=Releases
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #007800;">basedir</span>=Development
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #007800;">releasedir</span>=<span style="color: #007800;">$basedir</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span>
	<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>&quot;</span></pre></div></div>

<p>Each build target is then packaged, one at a time.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># Package each app</span>
	<span style="color: #000000; font-weight: bold;">for</span> app <span style="color: #000000; font-weight: bold;">in</span> build<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span>-iphoneos<span style="color: #000000; font-weight: bold;">/*</span>.app ; <span style="color: #000000; font-weight: bold;">do</span>
		<span style="color: #007800;"><span style="color: #c20cb9; font-weight: bold;">basename</span></span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(basename &quot;$app&quot; .app)</span>&quot;</span></pre></div></div>

<p>The application bundle is copied into a directory called <code>Payload/Payload</code>. The first directory name isn&#8217;t significant, but the second is important to make a working <code>.ipa</code> file.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> Payload<span style="color: #000000; font-weight: bold;">/</span>Payload
		<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-Rp</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>&quot;</span> Payload<span style="color: #000000; font-weight: bold;">/</span>Payload</pre></div></div>

<p>To have an icon in iTunes, the package must include a 512&#215;512 PNG or JPEG named <code>iTunesArtwork</code> at the root. The following code supports per-project default artwork as well as app-specific artwork (if there are multiple apps in a single project).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># Get app-specific iTunes artwork or project-specific artwork</span>
		<span style="color: #666666; font-style: italic;"># if available</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$basename</span>&quot;</span>.iTunesArtwork <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$basename</span>&quot;</span>.iTunesArtwork Payload<span style="color: #000000; font-weight: bold;">/</span>iTunesArtwork
		<span style="color: #000000; font-weight: bold;">elif</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> iTunesArtwork <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-f</span> iTunesArtwork Payload<span style="color: #000000; font-weight: bold;">/</span>iTunesArtwork
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>A <code>.ipa</code> file is just a <code>.zip</code> file with a particular content format. When building for distribution through the AppStore, the <code>.zip</code> extension is required. Otherwise the <code>.ipa</code> extension is used.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># Distribution builds have a .zip extension, development</span>
		<span style="color: #666666; font-style: italic;"># builds have a .ipa extension</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$config</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;Distribute&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #007800;">ext</span>=<span style="color: #c20cb9; font-weight: bold;">zip</span>
		<span style="color: #000000; font-weight: bold;">else</span>
			<span style="color: #007800;">ext</span>=ipa
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Next we use <code>ditto</code> to zip the contents, then delete the temp directory.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># zip the Payload directory then delete it</span>
		<span style="color: #007800;">output</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>/<span style="color: #007800;">$basename</span>.<span style="color: #007800;">$ext</span>&quot;</span>
		ditto <span style="color: #660033;">-c</span> <span style="color: #660033;">-k</span> Payload <span style="color: #ff0000;">&quot;<span style="color: #007800;">$output</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Failed to compress&quot;</span>
		<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> Payload</pre></div></div>

<p>We remember the name of the generated file to display at the end of the script.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># add to the list of output files</span>
		<span style="color: #007800;">all</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${all:+$(printf &quot;%s\n&quot; &quot;$all&quot;)}</span><span style="color: #007800;">$(printf &quot;\t%s&quot; &quot;$output&quot;)</span>&quot;</span></pre></div></div>

<p>XCode supports splitting the debug symbols from the app. If this option is enabled (as it should be for Release and Distribution builds) we save the debug symbols with the app:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># save debug symbols (if available) with the app</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>.dSYM&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #007800;">output</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>/<span style="color: #007800;">$basename</span>.dSYM.zip&quot;</span>
			ditto <span style="color: #660033;">-c</span> <span style="color: #660033;">-k</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>.dSYM&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$output</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Failed to compress debug info&quot;</span>
			<span style="color: #007800;">all</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(printf &quot;%s\n&quot; &quot;$all&quot;)</span><span style="color: #007800;">$(printf &quot;\t%s&quot; &quot;$output&quot;)</span>&quot;</span>
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Finally, we update a symlink to point to the latest version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># update a symlink to the latest version</span>
		<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$basedir</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span> ; <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-sf</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>/<span style="color: #007800;">$basename</span>.<span style="color: #007800;">$ext</span>&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<h4>Report Results</h4>
<p>Once all the builds have completed and been packaged, a build summary is displayed to the user.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># report the generated files</span>
<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;Created: <span style="color: #007800;">$all</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Balsamiq Mockups</title>
		<link>http://carpe-cocoa.com/2009-05-21/balsamiq-mockups/</link>
		<comments>http://carpe-cocoa.com/2009-05-21/balsamiq-mockups/#comments</comments>
		<pubDate>Fri, 22 May 2009 00:57:17 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://www.szczerba.net/?p=135</guid>
		<description><![CDATA[I&#8217;ve heard good things about Balsamiq Mockups so I thought I&#8217;d give it a try. The desktop version is currently just $79, and installs in moments from the Mockups site. The app is based on Adobe Air, so if you don&#8217;t have Air installed already, you&#8217;ll need to do that first. Mockups runs on OS [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve heard good things about <a href="http://www.balsamiq.com/products/mockups/">Balsamiq Mockups</a> so I thought I&#8217;d give it a try. The <a href="http://www.balsamiq.com/products/mockups/desktop">desktop version</a> is currently just $79, and <a href="http://www.balsamiq.com/products/mockups/desktop#download">installs in moments</a> from the Mockups site. The app is based on <a href="http://get.adobe.com/air/">Adobe Air</a>, so if you don&#8217;t have Air installed already, you&#8217;ll need to do that first. Mockups runs on OS X, Windows, and Linux. There is also a <a href="http://www.balsamiq.com/demos/mockups/Mockups.html">web version</a>. This review uses the OS X desktop version. You can try out the desktop version for free, but to save or export designs you&#8217;ll need a license key.</p>
<p><span id="more-135"></span></p>
<h4>Registration</h4>
<p>Registration is simple, although the menu item is hidden in the Help menu instead of being in the Application menu (which doesn&#8217;t actually exist). Once you&#8217;ve entered the registered name and serial number, the app is fully activated. Registration is per-user, not per-machine, so you can install it on your desktop, laptop, home desktop, etc. Registration includes free perpetual updates.</p>
<h4>Reinventing the&#8230; uh&#8230; clock</h4>
<p><a title="New Mockup Window" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-1.png" title="New Mockup Window" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-136" title="New Mockup Window" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-1-150x100.png" alt="New Mockup Window" width="150" height="100" /></a> When you launch Mockups, you are presented with a new mockup window, ready for your design. Across the top are a number of controls you can add to the Mockup. These controls are broken down into a number of categories. Since I write iPhone apps for a living, we&#8217;ll select the iPhone category to get started, then set about creating a workflow for the built-in clock app.</p>
<p><a title="iPhone Container Options" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-2.png" title="iPhone Container Options" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-140" title="iPhone Container Options" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-2-150x106.png" alt="iPhone Container Options" width="150" height="106" /></a> First, drag a iPhone object into the mockup to act as a container for our views. Bring up the properties window (it&#8217;s greyed out until you point at it) and select the middle background pattern, which shows a Nav Bar at the top and a Tab Bar at the bottom. Then click in the &#8220;Quick Add&#8221; box and start typing &#8220;Icon&#8221;. Select the &#8220;Icon and Text Label&#8221; and type in &#8220;World Clock&#8221;. Click on &#8220;Icon search&#8221; and type in &#8220;Circle&#8221;, then select the &#8220;Dot, Little Black Circle&#8221; icon. Change the font size to 9 and icon size to Small to make it fit better, and drag it over the tab bar area on the phone. In a similar way, we can quickly make the Alarm, Stopwatch, and Timer buttons and place them in their approximate locations. Select all 4 icons and Align Bottom, then Distribute Centers Horizontally and Group them. We&#8217;ll save this as &#8220;iPhone Clock App World Clock&#8221;.</p>
<p><a title="Completed World Clock Controls" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-3.png" title="Completed World Clock Controls" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-141" title="Completed World Clock Controls" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-3-150x106.png" alt="Completed World Clock Controls" width="150" height="106" /></a>Next we clone the mockup (??N) three times and save the clones as &#8220;iPhone Clock App Alarm&#8221;, &#8220;iPhone Clock App Stopwatch&#8221;, and &#8220;iPhone Clock App Timer&#8221;. Later we can link the icon buttons to the different views, but for now we&#8217;ll continue creating the World Clock view. In a few moments we can add an Edit button and a + button and use a Label to finish the Nav Bar.</p>
<p><a title="Completed World Clock View" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-4.png" title="Completed World Clock View" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-142" title="Completed World Clock View" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-4-150x106.png" alt="Completed World Clock View" width="150" height="106" /></a>Next we complete the content view. Simple add a Rectangle/Canvas to the content area, an icon for the clock, and a few Labels for the City, Time, AM/PM and Day, adjusting the fonts appropriately (remember, the goal is an approximate representation of the final app). Duplicate the row we just created a few times to fill out the content area.</p>
<h4>In-App Navigation</h4>
<p><a title="Adding Links" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-5.png" title="Adding Links" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-153" title="Adding Links" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-5-150x106.png" alt="Adding Links" width="150" height="106" /></a>The last step on this view is to fill out the links. Just select each control and choose the desired mockup from the Link dropdown. A small blue arrow will appear on the control. If you switch to View-&gt;Full Screen Presentation (?F) you can click on these linked buttons to navigate around the mockup.</p>
<p><a title="Timer Mockup" rel="lightbox[mockups]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-6.png" title="Timer Mockup" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-154" title="Timer Mockup" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-6-150x106.png" alt="Timer Mockup" width="150" height="106" /></a> We can use the included iPhone Picker control to quickly mockup the Timer screen as well. The buttons in the middle are made from Canvases and Labels to allow customizing the text layout and colors, much as we&#8217;d have to do in Interface Builder or programmatically if we were to build this app for real. It would be nice if Mockups let you change button colors. Maybe that feature will be added soon.</p>
<h4>Full Screen Presentation</h4>
<div class="alignright"><a title="Full Screen Mode, Big Pointer for Discussions" rel="lightbox[full screen]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-71.png" title="Full Screen Mode, Big Pointer for Discussions" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-156" title="Full Screen Mode, Big Pointer for Discussions" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-71-109x150.png" alt="Full Screen Mode, Big Pointer for Discussions" width="109" height="150" /></a><a title="Links are highlighted...." rel="lightbox[full screen]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-81.png" title="Links are highlighted...." rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-157" title="Links are highlighted...." src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-81-110x150.png" alt="Links are highlighted...." width="110" height="150" /></a> <a title="... and can be followed" rel="lightbox[full screen]" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-9.png" title="... and can be followed" rel="lightbox[135]"><img class="alignleft size-thumbnail wp-image-158" title="... and can be followed" src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-9-109x150.png" alt="... and can be followed" width="109" height="150" /></a></div>
<p>We can go on like this adding additional mockups until we&#8217;ve covered all the screens in the app. Along the way we can share the files with the rest of the team to get feedback much more quickly than if we were writing code for all of this. If you are in the same office as the rest of your team or use some sort of web collaboration software, you can use the Full Screen Presentation mode to click through the various screens in the app, using the ridiculously large pointer (and I mean that in a nice way) to point out parts of the interface as you discuss it.</p>
<h4>Conclusions</h4>
<p>Mockups is extremely easy to use. I wrote this review as I was learning the app for the first time. The hand-drawn images really do have the intended &#8220;lo-fi&#8221; effect, encouraging you to stay focused on the big picture instead of spending hours tweaking individual pixels. Mockups will definitely become part of the <a href="http://appmobi.com/">AppMobi</a> design process. It will be a big help as we move ahead with development of our more sophisticated productivity apps.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-21/balsamiq-mockups/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>WWDC Parties/Events &#8211; WWDC 2009</title>
		<link>http://carpe-cocoa.com/2009-05-21/wwdc-partiesevents-wwdc-2009/</link>
		<comments>http://carpe-cocoa.com/2009-05-21/wwdc-partiesevents-wwdc-2009/#comments</comments>
		<pubDate>Thu, 21 May 2009 21:04:22 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=169</guid>
		<description><![CDATA[June 4 Update: Added Loopt Mixer and Developer/Artist Meetup. Thanks LooptChris and Steve Weller!
There are a number of events going on around WWDC this year. Brandon Kwaselow has the most comprehensive list I&#8217;ve seen so far, it even includes Three Wolf Tuesday!
WWDC Parties/events &#8211; WWDC 2009 &#8211; Brandon &#8220;Quazie&#8221; Kwaselow&#8217;s Blog.
Google Calendar with the events: [...]]]></description>
			<content:encoded><![CDATA[<p><strong>June 4 Update:</strong> Added <a href="http://www.looptblog.com/2009/06/time-to-party-loopt-mixer-on-june-8.html" target="_blank">Loopt Mixer</a> and <a href="http://steveweller.com/articles/developer-artist-meetup-wwdc/" target="_blank">Developer/Artist Meetup</a>. Thanks <a href="http://www.looptblog.com/2009/06/time-to-party-loopt-mixer-on-june-8.html" target="_blank">LooptChris</a> and <a href="http://steveweller.com/" target="_blank">Steve Weller</a>!</p>
<p>There are a number of events going on around WWDC this year. Brandon Kwaselow has the most comprehensive list I&#8217;ve seen so far, it even includes Three Wolf Tuesday!</p>
<p><a href="http://blog.quazie.net/2009/05/wwdc-partiesevents/">WWDC Parties/events &#8211; WWDC 2009 &#8211; Brandon &#8220;Quazie&#8221; Kwaselow&#8217;s Blog</a>.</p>
<p><a href="http://www.google.com/calendar/embed?src=62mjk3b5jan9k5046cgdutgk30%40group.calendar.google.com">Google Calendar</a> with the events: <iframe src="https://www.google.com/calendar/embed?title=WWDC%20Parties%2FEvents%20-%20WWDC%202009&amp;showCalendars=0&amp;mode=AGENDA&amp;height=600&amp;wkst=1&amp;bgcolor=%23FFFFFF&amp;src=62mjk3b5jan9k5046cgdutgk30%40group.calendar.google.com&amp;color=%23A32929&amp;ctz=America%2FLos_Angeles" style=" border-width:0 " width="800" height="600" frameborder="0" scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-21/wwdc-partiesevents-wwdc-2009/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>First App Submission</title>
		<link>http://carpe-cocoa.com/2009-05-20/first-app-submission/</link>
		<comments>http://carpe-cocoa.com/2009-05-20/first-app-submission/#comments</comments>
		<pubDate>Wed, 20 May 2009 19:44:36 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://www.szczerba.net/?p=109</guid>
		<description><![CDATA[I just submitted AppMobi&#8217;s first product to the App Store.
We were looking for a fairly simple app to use as a learning experience. After toying with a few ideas, we ended up settling on a puzzle game that my son and I initially wrote during &#8220;take your kid to work day.&#8221; What started as a [...]]]></description>
			<content:encoded><![CDATA[<p>I just submitted <a href="http://appmobi.com">AppMobi</a>&#8217;s first product to the App Store.</p>
<p>We were looking for a fairly simple app to use as a learning experience. After toying with a few ideas, we ended up settling on a puzzle game that my son and I initially wrote during &#8220;take your kid to work day.&#8221; What started as a simple slide puzzle grew a number of features including tile spinning, image importing, picture taking, and more. Here&#8217;s the description from the app store:</p>
<div class="box">
<div class="wrapleft">
<div class="wrapright">
<div class="tr">
<div class="bl">
<div class="tl">
<div class="br the-content">SpinSlide is an enhanced iPhone version of the little plastic &#8220;15 sliding tiles&#8221; puzzle. The object of the game is to get the tiles in 1-15 order by sliding them, using the one open tile space. </p>
<p>But SpinSlide adds a whole new dimension to the simple &#8220;15&#8243; puzzle &#8230;</p>
<p>Unlike the classic game, SpinSlide pieces also rotate when shuffled. Finding their correct orientation is easy when the tiles are numbered, but SpinSlide lets you create challenging picture puzzles from our provided library, from your camera roll, and even by taking a photo.</p>
<p>To start, choose a puzzle, then shake your iPhone or Touch to jumble the pieces. Simply move the tiles with your finger. You can move a row of tiles by sliding the end tile. </p>
<p>To rotate a tile, tap and hold on the tile and it will &#8220;zoom&#8221; under your finger. Rotate your finger clockwise or counterclockwise and the tile will rotate as well. Let go and the tile will drop back into the puzzle. You can also rotate the piece after it zooms by touching the screen with another finger and moving the finger the way you want it to rotate.</p>
<p>Since most games are played during limited spare time, SpinSlide lets you determine how hard you want the puzzle to be. A simple numbered puzzle takes 3-5 minutes to solve, and one of our un-numbered hard puzzles can take as long as 20 minutes for the skilled player. </p>
<p>There are a ton of &#8220;me-too&#8221; slider puzzle games in the App Store, some priced higher than SpinSlide. SpinSlide brings the sliding tile puzzle to a whole new level with features like spinning tiles, built-in puzzles from easy to extremely hard, and the ability to use your own photos and drawings for puzzles. You&#8217;ll find SpinSlide to be an app that you enjoy playing over and over again whenever you have a few minutes to entertain yourself with a brain exercising puzzle.</p></div>
</div>
</div>
</div>
</div>
</div>
</div>
<p>And some screenshots:<br />
<a href="http://www.szczerba.net/wp-content/uploads/2009/05/main.jpg" title="Typical Gameplay" rel="lightbox[screenshots]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/main-104x150.jpg" alt="Typical Gameplay" title="Typical Gameplay" width="104" height="150" class="alignnone size-thumbnail wp-image-112" /></a> <a href="http://www.szczerba.net/wp-content/uploads/2009/05/extra1.jpg" title="Solved Number Puzzle" rel="lightbox[screenshots]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/extra1-104x150.jpg" alt="Solved Number Puzzle" title="Solved Number Puzzle" width="104" height="150" class="alignnone size-thumbnail wp-image-113" /></a> <a href="http://www.szczerba.net/wp-content/uploads/2009/05/extra2.jpg" title="Solved Custom Photo Puzzle" rel="lightbox[screenshots]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/extra2-104x150.jpg" alt="Solved Custom Photo Puzzle" title="Solved Custom Photo Puzzle" width="104" height="150" class="alignnone size-thumbnail wp-image-114" /></a> <a href="http://www.szczerba.net/wp-content/uploads/2009/05/extra3.jpg" title="These numbers can be hidden" rel="lightbox[screenshots]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/extra3-104x150.jpg" alt="These numbers can be hidden" title="These numbers can be hidden" width="104" height="150" class="alignnone size-thumbnail wp-image-115" /></a> <a href="http://www.szczerba.net/wp-content/uploads/2009/05/extra4.jpg" title="Options screen" rel="lightbox[screenshots]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/extra4-104x150.jpg" alt="Options screen" title="Options screen" width="104" height="150" class="alignnone size-thumbnail wp-image-116" /></a></p>
<p>Now it&#8217;s just a matter of waiting for Apple approval of both the SpinSlide application and AppMobi&#8217;s contracts. We&#8217;ll see which comes through first.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-20/first-app-submission/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installing AdHoc Applications on the iPhone</title>
		<link>http://carpe-cocoa.com/2009-05-12/installing-adhoc-applications-on-the-iphone/</link>
		<comments>http://carpe-cocoa.com/2009-05-12/installing-adhoc-applications-on-the-iphone/#comments</comments>
		<pubDate>Tue, 12 May 2009 19:26:19 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://www.szczerba.net/?p=73</guid>
		<description><![CDATA[If you&#8217;ve received an AdHoc iPhone application (a file with a .app extension) and associated provisioning file (a file with a .mobileprovision extension), follow these simple steps to install it on your iPhone.

Connect your iPhone or iPod Touch to a computer with iTunes installed.
Launch iTunes and switch to the Applications section of the Library

If this [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve received an AdHoc iPhone application (a file with a <code>.app</code> extension) and associated provisioning file (a file with a <code>.mobileprovision</code> extension), follow these simple steps to install it on your iPhone.</p>
<ol>
<li>Connect your iPhone or iPod Touch to a computer with iTunes installed.</li>
<li>Launch iTunes and switch to the Applications section of the Library<br />
<a title="Open iTunes to the Applications section of the Library" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-11.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-11-150x118.png" alt="iTunes Library Application Section" title="iTunes Library Application Section" width="150" height="118" class="alignnone size-thumbnail wp-image-93" /></a></li>
<li>If this is your first install of an app
<ol style="list-style-type:lower-alpha">
<li>Save the provisioning file to your desktop&#8230;<br />
<a title="Save the provisioning file to your desktop..." href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-10.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-10.png" alt="Saved Provisioning File on Desktop" title="Saved Provisioning File on Desktop" width="151" height="112" class="alignnone size-full wp-image-74" /></a></li>
<li>and drag it into iTunes<br />
<a title="Drag the provisioning file into iTunes" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-12.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-12-150x117.png" alt="Dragging the provisioning file into iTunes Library" title="Dragging the provisioning file into iTunes Library" width="150" height="117" class="alignnone size-thumbnail wp-image-94" /></a></li>
</ol>
</li>
<li>Save the application to your desktop&#8230;<br />
<a title="Save the application to your desktop..." href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-13.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-13.png" alt="App saved on Desktop" title="App saved on Desktop" width="139" height="102" class="alignnone size-full wp-image-80" /></a></li>
<li>and drag it into iTunes<br />
<a title="Drag the application into iTunes" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-14.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-14-150x116.png" alt="Dragging the app into the iTunes Library" title="Dragging the app into the iTunes Library" width="150" height="117" class="alignnone size-thumbnail wp-image-94" /></a></li>
<li>Select your to your iPhone or iPod in the Device section in the left column of iTunes; then go to the Applications tab.<br />
<a title="Check device's application settings in iTunes" href="http://www.szczerba.net/wp-content/uploads/2009/05/picture-151.png" rel="lightbox[steps]"><img src="http://www.szczerba.net/wp-content/uploads/2009/05/picture-151-150x112.png" alt="iTunes Device Applications Tab" title="iTunes Device Applications Tab" width="150" height="112" class="alignnone size-thumbnail wp-image-92" /></a></li>
<p>Make sure you&#8217;ve either selected &#8220;All Applications&#8221; or that the checkbox next to the new app is selected.</p>
<li>Click &#8220;Sync&#8221;</li>
<li>Enjoy!</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-12/installing-adhoc-applications-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

