<?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</title>
	<atom:link href="http://carpe-cocoa.com/tag/iphone/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>iPhone OS 3.0.1 Released</title>
		<link>http://carpe-cocoa.com/2009-07-31/iphone-os-3-0-1-released/</link>
		<comments>http://carpe-cocoa.com/2009-07-31/iphone-os-3-0-1-released/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 21:53:23 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=314</guid>
		<description><![CDATA[Apple has released iPhone OS 3.0.1. All iPhone users can (and should!) update for free through iTunes. If iTunes does not notify you that the update is available, click the &#8220;Check for Update&#8221; button on the device summary tab.
This update fixes the much-publicised SMS vulnerability, which could allow an attacker to access a phone through [...]]]></description>
			<content:encoded><![CDATA[<p>Apple has released iPhone OS 3.0.1. All iPhone users can (and should!) update for free through iTunes. If iTunes does not notify you that the update is available, click the &#8220;Check for Update&#8221; button on the device summary tab.</p>
<p>This update fixes the <a href="http://www.forbes.com/2009/07/28/hackers-iphone-apple-technology-security-hackers.html" target="_blank">much-publicised</a> <a href="http://news.cnet.com/8301-27080_3-10299378-245.html?tag=newsFeaturedBlogArea.0" target="_blank">SMS vulnerability</a>, which could allow an attacker to access a phone through a series of SMS messages, only one of which is visible to the user. It seems the bug is in the baseband code, possibly in reference code from the chip vendor, since a number of devices from different vendors are (or were) reportedly vulnerable to variants of this attack, including Android and HTC WinMo devices.</p>
<p><a href="http://support.apple.com/kb/HT3754" target="_blank">Apple&#8217;s knowledge base article</a> on the update has little new info.</p>
<p>iPod Touch users are unaffected by this update, since they do not have SMS capability. The iPhone OS for iPod Touch remains at version 3.0. The update does not seem to affect tethering either.</p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-07-31/iphone-os-3-0-1-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GameKit Troubleshooting</title>
		<link>http://carpe-cocoa.com/2009-07-22/gamekit-troubleshooting/</link>
		<comments>http://carpe-cocoa.com/2009-07-22/gamekit-troubleshooting/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 00:23:31 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[appMobi]]></category>
		<category><![CDATA[BeamCatcher]]></category>
		<category><![CDATA[PhotoBeamer]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=294</guid>
		<description><![CDATA[EDIT August 19, 2009: Added information about server timeouts.
GameKit is a new feature in iPhone OS 3.0 that allows apps to easily exchange data over a Bluetooth Personal Area Networking (PAN). Apple did a great job making this functionality available, but there are a few issues users may see with these applications. If you are [...]]]></description>
			<content:encoded><![CDATA[<p><em>EDIT August 19, 2009: Added information about server timeouts.</em></p>
<p>GameKit is a new feature in iPhone OS 3.0 that allows apps to easily exchange data over a Bluetooth Personal Area Networking (PAN). Apple did a great job making this functionality available, but there are a few issues users may see with these applications. If you are having problems connecting with a GameKit app such as <a title="See PhotoBeamer in the App Store (opens in iTunes)" 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 (opens in iTunes)" href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=321815121&amp;mt=8 " target="_blank">BeamCatcher</a>, try the following steps to resolve the issue.</p>
<ol>
<li><strong>Be sure you are using a supported device.</strong> The original iPhone (which has a silver back) and the original iPod Touch (which lacks hardware volume controls on the side) do not have the necessary hardware to support PhotoBeamer or other GameKit apps.</li>
<li><strong>Be sure Bluetooth is on.</strong> You should see a Bluetooth icon next to the battery icon like this: <img class="alignnone size-full wp-image-295" title="Bluetooth In Status Bar" src="http://carpe-cocoa.com/wp-content/uploads/2009/07/Bluetooth-In-Status-Bar.png" alt="Bluetooth In Status Bar" width="41" height="17" />. It&#8217;s OK if it&#8217;s grey, but it must be there.<sup><small><a id="ref1" href="#1">[1]</a></small></sup></li>
<li><strong>Turn off WiFi.</strong> The WiFi and Bluetooth radios operate on the same frequency band and share an antenna. Turning off WiFi ensures that the maximum bandwidth is available to the Bluetooth connection.<sup><small><a id="ref2" href="#2">[2]</a></small></sup></li>
<li><strong>Be patient.</strong> The Bluetooth radio powers down if it has not been used for a while, and takes some time to start up. It can also take some time for two unpaired devices to synchronize and start to transfer data. Allow a minute or so before giving up on a connection. It&#8217;s often faster, but this is not something we have control over.</li>
<li id="idle_timeout"><strong><em>(Added 8/19/09) </em>If changing servers, be prepared to wait.</strong> Developers do not have direct control over the Bluetooth PAN. It is created automatically when a connection is made, and is torn down after it has been idle for some time. Unfortunately, each device can only have one outgoing (client mode) PAN active at a time. For PhotoBeamer, this means that if you are viewing photos from one friend, then try to disconnect and view another friend&#8217;s photos, it will take a long time for the second friend&#8217;s phone to show up. This can also happen when switching between different PAN apps.</li>
<li><strong>If all else fails, restart</strong> the app or even the device. Sometimes the resolver just stops seeing a particular device.<sup><small><a id="ref3" href="#3">[3]</a></small></sup> We expect this to improve with future iPhone OS updates as the technology matures.</li>
</ol>
<p>Networking is easy in a perfect environment. It&#8217;s hard in the real world (at the OS level at least, modern operating systems shield the developer from much of this), and it&#8217;s even harder when it&#8217;s a decentralized, low-power wireless network like Bluetooth. I spent years working on this sort of thing at a very low level in very demanding environments. I definitely feel for the Apple engineers trying to make this a smooth, painless user experience, but it&#8217;s not quite there yet. Until it is, I&#8217;ll continue to look for new ways to improve the experience within the confines of the iPhone SDK.</p>
<p>&#8212;</p>
<ol>
<li id="1">Apps that use the Apple-provided peer picker will offer to turn on Bluetooth for you. Apps such as PhotoBeamer which allow connections at any time or use a custom peer selection UI for another reason can warn you that Bluetooth is disabled but can not turn it on. You need to go to the Settings app and turn it on yourself. <small><a href="#ref1">[BACK]</a></small></li>
<li id="2">See, you have to go to the Settings App anyway! <small><a href="#ref2">[BACK]</a></small></li>
<li id="3"><em> (Added 8/19/09)</em> This is probably because of the limited number of outgoing PAN connections and <a href="#idle_timeout">idle timeout issue</a>. <small><a href="#ref3">[BACK]</a></small></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-07-22/gamekit-troubleshooting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PhotoBeamer Coverage</title>
		<link>http://carpe-cocoa.com/2009-07-20/photobeamer-coverage/</link>
		<comments>http://carpe-cocoa.com/2009-07-20/photobeamer-coverage/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 16:26:29 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[appMobi]]></category>
		<category><![CDATA[BeamCatcher]]></category>
		<category><![CDATA[PhotoBeamer]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=284</guid>
		<description><![CDATA[Since PhotoBeamer went live, I&#8217;ve been watching the comments and reviews coming in and working on a number of updates and improvements. I&#8217;m just about ready to submit the 1.1 version to the App Store. The new version has a number of improvements I think you&#8217;ll like.
We&#8217;ve also sent out a number of promo codes [...]]]></description>
			<content:encoded><![CDATA[<p>Since PhotoBeamer went live, I&#8217;ve been watching the comments and reviews coming in and working on a number of updates and improvements. I&#8217;m just about ready to submit the 1.1 version to the App Store. The new version has a number of improvements I think you&#8217;ll like.</p>
<p>We&#8217;ve also sent out a number of promo codes to various review sites, so hopefully we&#8217;ll see some in-depth reviews soon. In the mean time, I found launch-day reviews from <a title="Today's Notable iPhone Apps - Monday July 13th Edition : iSmashPhone" href="http://www.ismashphone.com/2009/07/todays-notable-iphone-apps-monday-july-13th-edition.html" target="_blank">iSmashPhone</a> and <a title="Use PhotoBeamer To Send And Recieve Photos Over Bluetooth : App Advice" href="http://appadvice.com/appnn/2009/07/use-photobeamer-to-send-and-recieve-photos-over-bluetooth/" target="_blank">App Advice</a>. If you know of another site that&#8217;s reviewed PhotoBeamer and BeamCatcher, let me know!</p>
<p><strong>Update:</strong> PhotoBeamer was reviewed on <a title="Weird + Small Apps 22: Feed Me!, SNS Contact, PhotoBeamer, Ghostly Discovery + More : iLounge Article" href="http://www.ilounge.com/index.php/articles/comments/weird-small-apps-22-feed-me-sns-contact-photobeamer-ghostly-discovery-more/" target="_blank">iLounge</a> today. They rated it a B-, and said &#8220;A legitimately useful tool&#8221;.. &#8220;Apple should add more features like this but until it does, PhotoBeamer is a fine option&#8221;. They did seem to miss that BeamCatcher is available as a free viewer though. <em>(added July 22, 2009)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-07-20/photobeamer-coverage/feed/</wfw:commentRss>
		<slash:comments>0</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>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>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>
