<?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>bunnyhero dev &#187; iPhone</title>
	<atom:link href="http://www.bunnyhero.org/category/iphone/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bunnyhero.org</link>
	<description>Notes on iPhone, Flash and Web development</description>
	<lastBuildDate>Fri, 23 Jul 2010 18:00:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Loading an image mask from a file</title>
		<link>http://www.bunnyhero.org/2010/07/23/loading-an-image-mask-from-a-file/</link>
		<comments>http://www.bunnyhero.org/2010/07/23/loading-an-image-mask-from-a-file/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 15:00:22 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[cgimage]]></category>
		<category><![CDATA[coregraphics]]></category>
		<category><![CDATA[graphics]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=334</guid>
		<description><![CDATA[Core Graphics image masks are handy, but if you want to load the mask image from a file, things don&#8217;t always work the way you expect. The function CGImageCreateWithMask() can take either a mask or an image as the second parameter, but it turns out that Core Graphics (at least on iOS) is pretty picky about what is an acceptable image for the mask. I&#8217;ve seen this snippet of code suggested in a few places: CGImageRef mask = CGImageMaskCreate&#40;CGImageGetWidth&#40;image&#41;, CGImageGetHeight&#40;image&#41;, CGImageGetBitsPerComponent&#40;image&#41;, CGImageGetBitsPerPixel&#40;image&#41;, CGImageGetBytesPerRow&#40;image&#41;, CGImageGetDataProvider&#40;image&#41;, NULL, false&#41;; the idea being that you create a mask with the pixels that are in the loaded image, but it turns out that this code is not 100% reliable either. The truth of the matter is that CGImage is an incredibly versatile object. The bits that represent the image can be in a variety of formats, bit depths, and colour space. When you load an image from a file, you are not guaranteed what format those bits are going to be in—for example, there are reports online of how people can get image masks to work if they save it in one way from an image editing program, but not if they save it a [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.bunnyhero.org/wp-content/uploads/2010/07/imagemask-illo.png" alt="illustration of an image being masked" title="image masking" width="450" height="180" class="aligncenter size-full wp-image-347" /><br />
Core Graphics image masks are handy, but if you want to load the mask image from a file, things don&#8217;t always work the way you expect.</p>
<p>The function <a href="http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CGImage/Reference/reference.html#jumpTo_8"><code>CGImageCreateWithMask()</code></a> can take either a mask or an image as the second parameter, but it turns out that Core Graphics (at least on iOS) is pretty picky about what is an acceptable image for the mask.</p>
<p>I&#8217;ve seen this snippet of code suggested in a few places:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">CGImageRef mask <span style="color: #002200;">=</span> CGImageMaskCreate<span style="color: #002200;">&#40;</span>CGImageGetWidth<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>,
CGImageGetHeight<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>, CGImageGetBitsPerComponent<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>,
CGImageGetBitsPerPixel<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>, CGImageGetBytesPerRow<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>,
CGImageGetDataProvider<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>, <span style="color: #a61390;">NULL</span>, <span style="color: #a61390;">false</span><span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>the idea being that you create a mask with the pixels that are in the loaded image, but it turns out that this code is not 100% reliable either.</p>
<p>The truth of the matter is that CGImage is an incredibly versatile object. The bits that represent the image can be in a variety of formats, bit depths, and colour space. When you load an image from a file, you are not guaranteed what format those bits are going to be in—for example, there are reports online of how people can get image masks to work if they save it in one way from an image editing program, but not if they save it a different way (e.g. <a href="http://stackoverflow.com/questions/1133248/any-idea-why-this-image-masking-code-does-not-work">http://stackoverflow.com/questions/1133248/any-idea-why-this-image-masking-code-does-not-work</a> )</p>
<p>Thus, I&#8217;ve found that the best and most reliable way to generate an image mask from an arbitrary image is to do this:</p>
<ol>
<li>Create a bitmap graphics context that is in an acceptable format for image masks</li>
<li>Draw your image into this bitmap graphics context</li>
<li>Create the image mask from the bits of the bitmap graphics context.</li>
</ol>
<p>The following function has worked well for me so far:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">CGImageRef createMaskWithImage<span style="color: #002200;">&#40;</span>CGImageRef image<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> maskWidth               <span style="color: #002200;">=</span> CGImageGetWidth<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">int</span> maskHeight              <span style="color: #002200;">=</span> CGImageGetHeight<span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">//  round bytesPerRow to the nearest 16 bytes, for performance's sake</span>
    <span style="color: #a61390;">int</span> bytesPerRow             <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>maskWidth <span style="color: #002200;">+</span> <span style="color: #2400d9;">15</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&amp;</span> 0xfffffff0;
    <span style="color: #a61390;">int</span> bufferSize              <span style="color: #002200;">=</span> bytesPerRow <span style="color: #002200;">*</span> maskHeight;
&nbsp;
    <span style="color: #11740a; font-style: italic;">//  we use CFData instead of malloc(), because the memory has to stick around</span>
    <span style="color: #11740a; font-style: italic;">//  for the lifetime of the mask. if we used malloc(), we'd have to</span>
    <span style="color: #11740a; font-style: italic;">//  tell the CGDataProvider how to dispose of the memory when done. using</span>
    <span style="color: #11740a; font-style: italic;">//  CFData is just easier and cleaner.</span>
&nbsp;
    CFMutableDataRef dataBuffer <span style="color: #002200;">=</span> CFDataCreateMutable<span style="color: #002200;">&#40;</span>kCFAllocatorDefault, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
    CFDataSetLength<span style="color: #002200;">&#40;</span>dataBuffer, bufferSize<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">//  the data will be 8 bits per pixel, no alpha</span>
    CGColorSpaceRef colourSpace <span style="color: #002200;">=</span> CGColorSpaceCreateDeviceGray<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    CGContextRef ctx            <span style="color: #002200;">=</span> CGBitmapContextCreate<span style="color: #002200;">&#40;</span>CFDataGetMutableBytePtr<span style="color: #002200;">&#40;</span>dataBuffer<span style="color: #002200;">&#41;</span>,
                                                        maskWidth, maskHeight,
                                                        <span style="color: #2400d9;">8</span>, bytesPerRow, colourSpace, kCGImageAlphaNone<span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">//  drawing into this context will draw into the dataBuffer.</span>
    CGContextDrawImage<span style="color: #002200;">&#40;</span>ctx, CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">0</span>, maskWidth, maskHeight<span style="color: #002200;">&#41;</span>, image<span style="color: #002200;">&#41;</span>;
    CGContextRelease<span style="color: #002200;">&#40;</span>ctx<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">//  now make a mask from the data.</span>
    CGDataProviderRef dataProvider  <span style="color: #002200;">=</span> CGDataProviderCreateWithCFData<span style="color: #002200;">&#40;</span>dataBuffer<span style="color: #002200;">&#41;</span>;
    CGImageRef mask                 <span style="color: #002200;">=</span> CGImageMaskCreate<span style="color: #002200;">&#40;</span>maskWidth, maskHeight, <span style="color: #2400d9;">8</span>, <span style="color: #2400d9;">8</span>, bytesPerRow,
                                                        dataProvider, <span style="color: #a61390;">NULL</span>, FALSE<span style="color: #002200;">&#41;</span>;
&nbsp;
    CGDataProviderRelease<span style="color: #002200;">&#40;</span>dataProvider<span style="color: #002200;">&#41;</span>;
    CGColorSpaceRelease<span style="color: #002200;">&#40;</span>colourSpace<span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span>dataBuffer<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> mask;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>Example of use:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">UIImage <span style="color: #002200;">*</span>maskSource <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mask.png&quot;</span><span style="color: #002200;">&#93;</span>;
CGImageRef mask <span style="color: #002200;">=</span> createMaskWithImage<span style="color: #002200;">&#40;</span>maskSource.CGImage<span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>Then use the mask as you wish, for example in the aforementioned <code>CGImageCreateWithMask()</code> or <a href="http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html#//apple_ref/doc/uid/TP30000950-CH1g-BCIICIIE"><code>CGContextClipToMask()</code></a></p>
<p>And don&#8217;t forget to dispose of the mask when you&#8217;re done. <code>createMaskWithImage()</code> returns the mask with a retain count of 1, and expects the caller to take ownership.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">CGImageRelease<span style="color: #002200;">&#40;</span>mask<span style="color: #002200;">&#41;</span>;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/07/23/loading-an-image-mask-from-a-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uncanny resemblance</title>
		<link>http://www.bunnyhero.org/2010/06/07/uncanny-resemblance/</link>
		<comments>http://www.bunnyhero.org/2010/06/07/uncanny-resemblance/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 03:37:03 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[1984]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[wwdc]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=327</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.bunnyhero.org/wp-content/uploads/2010/06/2010-1984.jpg"><img src="http://www.bunnyhero.org/wp-content/uploads/2010/06/2010-1984-300x133.jpg" alt="" title="2010 - 1984" width="300" height="133" class="aligncenter size-medium wp-image-328" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/06/07/uncanny-resemblance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Planet iDev tweak</title>
		<link>http://www.bunnyhero.org/2010/03/04/planet-idev-tweak/</link>
		<comments>http://www.bunnyhero.org/2010/03/04/planet-idev-tweak/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 22:04:34 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[planet idev]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=325</guid>
		<description><![CDATA[Some of the articles included by Planet iDev were getting pretty long, so I&#8217;ve decided to display just excerpts of the posts on the website rather than the entire articles. The RSS/Atom feeds should still have the full text. Some of the excerpts seem to be showing up empty. I&#8217;m not 100% sure of what is causing that, but I&#8217;ll look into it (I made some changes to FeedWordPress, so it&#8217;s likely something I did :) Thanks!]]></description>
			<content:encoded><![CDATA[<p>Some of the articles included by Planet iDev were getting pretty long, so I&#8217;ve decided to display just excerpts of the posts on the website rather than the entire articles. The RSS/Atom feeds should still have the full text.</p>
<p>Some of the excerpts seem to be showing up empty. I&#8217;m not 100% sure of what is causing that, but I&#8217;ll look into it (I made some changes to FeedWordPress, so it&#8217;s likely something I did :)</p>
<p>Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/03/04/planet-idev-tweak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Planet iDev</title>
		<link>http://www.bunnyhero.org/2010/01/31/planet-idev/</link>
		<comments>http://www.bunnyhero.org/2010/01/31/planet-idev/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 06:21:46 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[planet]]></category>
		<category><![CDATA[planet idev]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=309</guid>
		<description><![CDATA[When I was doing more Flash development, one of the most valuable web resources I used was Adobe Feeds. It aggregates many, many Adobe-oriented developer blogs from all over the web. Not only is it a great place to keep an eye on the pulse of the Flash development world, but it&#8217;s where smaller Flash developers can get more exposure to more of the community. Thanks to my own blog&#8217;s inclusion in Adobe Feeds, I was able to get some answers to some Flash questions more quickly than I probably would have otherwise, all while sharing what knowledge I had to as broad an audience as possible. When I started doing iPhone development, I looked for something similar for iPhone dev blogs. While there are a lot of iPhone developers out there blogging, I could not find a good aggregator out there. I did find Planet iPhone SDK, but it does not seem to be active (I tried contacting the owner, but did not receive a response). Planet Cocoa is good and quite active, but iPhone development is just part of the coverage there (the rest is Mac desktop development, which I don&#8217;t do myself). Thus, I am starting Planet [...]]]></description>
			<content:encoded><![CDATA[<p>When I was doing more Flash development, one of the most valuable web resources I used was <a href="http://feeds.adobe.com/">Adobe Feeds</a>. It aggregates many, many Adobe-oriented developer blogs from all over the web. Not only is it a great place to keep an eye on the pulse of the Flash development world, but it&#8217;s where smaller Flash developers can get more exposure to more of the community. Thanks to my own blog&#8217;s inclusion in Adobe Feeds, I was able to get some answers to some Flash questions more quickly than I probably would have otherwise, all while sharing what knowledge I had to as broad an audience as possible.</p>
<p>When I started doing iPhone development, I looked for something similar for iPhone dev blogs. While there are a lot of iPhone developers out there blogging, I could not find a good aggregator out there. I did find <a href="http://planetiphonesdk.com/">Planet iPhone SDK</a>, but it does not seem to be active (I tried contacting the owner, but did not receive a response). <a href="http://www.planetcocoa.org/">Planet Cocoa</a> is good and quite active, but iPhone development is just part of the coverage there (the rest is Mac desktop development, which I don&#8217;t do myself).</p>
<p>Thus, I am starting <a href="http://planetidev.bunnyhero.org/">Planet iDev</a>. Armed with <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> and a free WordPress theme, I have cobbled together a simple blog aggregator. I should note that many of the blogs I am aggregating I found on this <a href="http://www.travisdunn.com/iphone-developer-development-blogs/">tremendously helpful post</a> by <a href="http://www.travisdunn.com/">Travis Dunn</a>.</p>
<p>Having never run a blog aggregator before, I am unsure of the ethics and etiquette of <a href="http://www.planetplanet.org/">Planet</a>-style sites. I have no intention of financially profiting from other people&#8217;s hard work, nor do I want to negatively impact others&#8217; endeavours. With that in mind:</p>
<ul>
<li>There will never, <em>ever</em> be ads on Planet iDev</li>
<li>All authors are credited, and all articles link back to their original sources (as do all of the items in the <a href="http://feeds.feedburner.com/planetidev">Planet iDev feed</a>).</li>
<li>I have set up the WordPress install to <em>not</em> be indexed by search engines.</li>
</ul>
<p>Regardless, if any blog owner wants to be removed from this aggregation, I will be more than happy to do so, and I offer my sincerest apologies.</p>
<p>On the other, if any iPhone developer out there wants their blog to be added to this Planet, simply email me at planetidev@gmail.com (or comment on this post) with your blog&#8217;s information, and it will be considered for inclusion. Preference will be given to blogs that focus on the development and production process, rather than blogs that are mostly for product promotion.</p>
<p>I still have some questions regarding Planet etiquette. While most Planet sites seem to include the entire contents of the aggregated blogs&#8217; posts, I wonder if it would be more polite to only display an excerpt (but include the entire article in the feed). Please share any thoughts you have on this matter, or on Planet iDev in general.</p>
<p>I hope others out there find this resource valuable and useful, and I hope this helps encourage a sense of community. Thanks!</p>
<p>Visit <a href="http://planetidev.bunnyhero.org/">Planet iDev</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/01/31/planet-idev/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPhone offline web applications: tips and gotchas</title>
		<link>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/</link>
		<comments>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 01:13:29 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[application cache]]></category>
		<category><![CDATA[gotchas]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=283</guid>
		<description><![CDATA[I spent this evening updating my &#8220;iPhone VR&#8221; Javascript/CSS demo to work with iPhone OS 3.0 (it had stopped working 100% correctly since the OS update). I also decided to spend some time making it work as an offline-capable web application. The basic process of making your web app cacheable offline is, in theory, fairly straightforward, and generally well-documented at Apple&#8217;s website. I ran into some interesting headaches though. Gotchas: First thing to note is that your web server must serve your cache manifest file with a MIME type of text/cache-manifest. This may mean editing mime.types to add a line that looks like this: text/cache-manifest manifest or perhaps a line in httpd.conf that looks like this: AddType text/cache-manifest .manifest The next thing that had me stumped for a while: while your web server may know how to take the URL http://example.com/webapp/ and automatically and invisibly serve up the file http://example.com/webapp/index.html, your offline web app knows nothing of this mapping of webapp/ to webapp/index.html. If the URL bar reads http://example.com/webapp/ and you save it locally using a home screen bookmark, it will fail to launch correctly if the device is offline, even if index.html file has been cached. The device simply [...]]]></description>
			<content:encoded><![CDATA[<p>I spent this evening updating my <a href="http://www.bunnyhero.org/2008/10/13/iphone-vr-viewing-3d-panoramas-in-safari-using-javascript-and-webkit-transform/">&#8220;iPhone VR&#8221; Javascript/CSS demo</a> to work with iPhone OS 3.0 (it had stopped working 100% correctly since the OS update). I also decided to spend some time making it work as an <strong>offline-capable web application</strong>.</p>
<p>The basic process of making your web app cacheable offline is, in theory, fairly straightforward, and generally <a href = "http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html" >well-documented at Apple&#8217;s website</a>. I ran into some interesting headaches though.</p>
<h3>Gotchas:</h3>
<ul>
<li>First thing to note is that your <strong>web server must serve your cache manifest file with a MIME type of <code>text/cache-manifest</code></strong>. This may mean editing <code>mime.types</code> to add a line that looks like this:

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">text/cache-manifest   manifest</pre></div></div>

<p>or perhaps a line in <code>httpd.conf</code> that looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">AddType</span> text/cache-manifest  .manifest</pre></div></div>

</li>
<li>The next thing that had me stumped for a while: while your web server may know how to take the URL <code>http://example.com/<strong>webapp/</strong></code> and automatically and invisibly serve up the file <code>http://example.com/<strong>webapp/index.html</strong></code>, <strong>your offline web app knows nothing of this mapping of <code>webapp/</code> to <code>webapp/index.html</code></strong>. If the URL bar reads <code>http://example.com/webapp/</code> and you save it locally using a home screen bookmark, <strong>it will fail to launch correctly if the device is offline, even if <code>index.html</code> file has been cached</strong>. The device simply does not know to look for <code>webapp/index.html</code> instead of <code>webapp/</code>. Thus, you must ensure that the URL bar reads <code>webapp/index.html</code> before the user makes a home screen bookmark.</li>
<li>At first, I thought I would enforce the above with a tiny bit of JavaScript that simply reads <code>window.location</code> and redirects to <code>window.location + "index.html"</code> if the URL ends in a slash. This worked while online, but it broke my app when offline, even when the redirection was not taken. Why? It seems that <strong>any reference to <code>window.location</code> in your script is treated as network access. Since the device is offline, it generates an error alert.</strong>
<p>Instead, I made my app live at <code>webapp/main.html</code>, and created a small <code>webapp/index.html</code> file that simply redirects to <code>main.html</code>. (I could have used a server redirect inside of an <code>.htaccess</code> file instead, but I chose not to, for no particular reason.)</li>
</ul>
<h3>Tips:</h3>
<ul>
<li>You can specify a <strong>custom icon for the home screen bookmark</strong> using a <code>&lt;link&gt;</code> element, like so:

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;custom_icon.png&quot; /&gt;</pre></div></div>

<p><strong>If you don&#8217;t want iPhone to automatically apply the &#8220;shine&#8221; effect on your icon,</strong> use the following instead:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-icon-precomposed&quot; href=&quot;custom_icon.png&quot; /&gt;</pre></div></div>

</li>
<li>Since iPhone OS 3.0, <strong>offline web apps can have custom splash screens</strong>, just a like a native app! Simply add a <code>link</code> element to your web page:

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-startup-image&quot; href=&quot;/splash.png&quot; /&gt;</pre></div></div>

</li>
</ul>
<p>If you want to see the results of all this, go to <a href="http://bunnyherolabs.com/iphone/xform/">http://bunnyherolabs.com/iphone/xform/</a> on your iPhone or iPod Touch, then click the &#8220;+&#8221; (add bookmark) button and choose &#8220;Add to Home Screen.&#8221; Now you can click on the &#8220;Panorama&#8221; icon on your home screen to see the demo at any time, even when not connected to the internet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Easter egg in your iPhone app? Don&#8217;t hide it from Apple</title>
		<link>http://www.bunnyhero.org/2009/10/21/easter-egg-in-your-iphone-app/</link>
		<comments>http://www.bunnyhero.org/2009/10/21/easter-egg-in-your-iphone-app/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 22:06:12 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[apple]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=266</guid>
		<description><![CDATA[Yesterday, when I logged into the iPhone Dev Centre, I was greeted with a &#8220;please agree to the new developer agreement&#8221; alert. As usual, I copied the text and diffed it with the previous version. The bulk of the changes had to do with allowing in-app purchases in free apps. But the following change caught my eye: in section 12.2, &#8220;Termination&#8221;: 12.2 Termination This Agreement and all rights and licenses granted by Apple hereunder and any services provided hereunder will terminate, effective immediately upon notice from Apple: &#8230; (f) if You engage, or encourage others to engage, in any misleading, fraudulent, improper, unlawful or dishonest act relating to this Agreement, including, but not limited to, misrepresenting the nature of Your submitted Application (e.g., hiding or trying to hide functionality from Apple’s review). (emphasis added) So be careful, hidden-unlockable-feature-mongers. Apple could terminate your licence!]]></description>
			<content:encoded><![CDATA[<p>Yesterday, when I logged into the iPhone Dev Centre, I was greeted with a &#8220;please agree to the new developer agreement&#8221; alert. As usual, I copied the text and diffed it with the previous version. The bulk of the changes had to do with allowing in-app purchases in free apps.</p>
<p>But the following change caught my eye: in section 12.2, &#8220;Termination&#8221;:</p>
<blockquote><p>12.2 Termination<br />
This Agreement and all rights and licenses granted by Apple hereunder and any services provided hereunder will terminate, effective immediately upon notice from Apple:<br />
&#8230;<br />
(f) if You engage, or encourage others to engage, in any misleading, fraudulent, improper, unlawful or dishonest act relating to this Agreement, including, but not limited to, misrepresenting the nature of Your submitted Application<strong> (e.g., hiding or trying to hide functionality from Apple’s review).</strong>
</p></blockquote>
<p><strong>(emphasis added)</strong></p>
<p>So be careful, hidden-unlockable-feature-mongers. Apple could terminate your licence!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/10/21/easter-egg-in-your-iphone-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Genesis^H^H^H^H^H^H^H Droid Does</title>
		<link>http://www.bunnyhero.org/2009/10/18/genesishhhhhhh-droid-does/</link>
		<comments>http://www.bunnyhero.org/2009/10/18/genesishhhhhhh-droid-does/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 21:45:06 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Video games]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[droid]]></category>
		<category><![CDATA[genesis]]></category>
		<category><![CDATA[nintendo]]></category>
		<category><![CDATA[retro]]></category>
		<category><![CDATA[sega]]></category>
		<category><![CDATA[verizon]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=261</guid>
		<description><![CDATA[Verizon&#8217;s hard-hitting &#8220;Droid Does&#8221; anti-iPhone ad (via TechCrunch): I love my iPhone (and developing for it) but I definitely would like to see more competition in this space. I think this ad hits home for those of us who are frustrated with the iPhone&#8217;s shortcomings. On the other hand, the style of the end of the video makes me think of trailers for horror movies. I&#8217;m not sure that&#8217;s such a good association to make! This ad campaign also reminds me of the old Sega Genesis commercials back in the day:]]></description>
			<content:encoded><![CDATA[<p>Verizon&#8217;s hard-hitting &#8220;Droid Does&#8221; anti-iPhone ad (via TechCrunch):</p>
<p><object width="445" height="364"><param name="movie" value="http://www.youtube-nocookie.com/v/dPYM-XTqcec&#038;hl=en&#038;fs=1&#038;rel=0&#038;border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube-nocookie.com/v/dPYM-XTqcec&#038;hl=en&#038;fs=1&#038;rel=0&#038;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"></embed></object></p>
<p>I love my iPhone (and developing for it) but I definitely would like to see more competition in this space. I think this ad hits home for those of us who are frustrated with the iPhone&#8217;s shortcomings. On the other hand, the style of the end of the video makes me think of trailers for horror movies. I&#8217;m not sure that&#8217;s such a good association to make!</p>
<p>This ad campaign also reminds me of the old Sega Genesis commercials back in the day:<br />
<object width="445" height="364"><param name="movie" value="http://www.youtube-nocookie.com/v/k7nsBoqJ6s8&#038;hl=en&#038;fs=1&#038;rel=0&#038;border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube-nocookie.com/v/k7nsBoqJ6s8&#038;hl=en&#038;fs=1&#038;rel=0&#038;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/10/18/genesishhhhhhh-droid-does/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flash and iPhone</title>
		<link>http://www.bunnyhero.org/2009/10/11/flash-and-iphone/</link>
		<comments>http://www.bunnyhero.org/2009/10/11/flash-and-iphone/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 19:47:18 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=249</guid>
		<description><![CDATA[It&#8217;s been a few days now since Adobe announced that Flash CS5 Professional will have a &#8220;publish for iPhone&#8221; feature for ActionScript 3 projects. Just wanted to jot down a few thoughts: As a Flash developer and geek, the technology seems pretty damn impressive to me. It actually includes the LLVM compiler? Wild. Still, there are technical concerns, although to be fair, there are many months before CS5 ships. And for the moment, Flash-built apps won&#8217;t have access to things like the iPhone&#8217;s native UIKit controls, but they will have access to the accelerometer and multitouch (which at first I thought they did not). Furthermore, as an iPhone developer, I have concerns, and in a way these concerns have less to do with Adobe&#8217;s actions than Apple&#8217;s: the single chokepoint that is the App Store and its review/approval system. It&#8217;s clear that Apple&#8217;s review system does not scale (longer and longer delays in approvals), and discoverability is bad enough as it is with the number of apps in the store now and the limited number of ways there are to browse and find things in the store. If the iPhone app ecosystem was completely open, with many &#8220;stores&#8221; and multiple [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a few days now since Adobe announced that <a href="http://www.adobe.com/go/iphone">Flash CS5 Professional will have a &#8220;publish for iPhone&#8221;</a> feature for ActionScript 3 projects. Just wanted to jot down a few thoughts:</p>
<p>As a Flash developer and geek, the technology seems pretty damn impressive to me. It actually includes the LLVM compiler? Wild.</p>
<p>Still, there are <a href="http://devwhy.blogspot.com/2009/10/flash-on-iphone.html">technical concerns</a>, although to be fair, there are many months before CS5 ships. And for the moment, Flash-built apps won&#8217;t have access to things like the iPhone&#8217;s native UIKit controls, but they will have access to the accelerometer and multitouch (which at first I thought they did not).</p>
<p>Furthermore, as an iPhone developer, I have concerns, and in a way these concerns have less to do with Adobe&#8217;s actions than Apple&#8217;s: the single chokepoint that is the App Store and its review/approval system. It&#8217;s clear that Apple&#8217;s review system does not scale (longer and longer delays in approvals), and discoverability is bad enough as it is with the number of apps in the store now and the limited number of ways there are to browse and find things in the store.</p>
<p>If the iPhone app ecosystem was completely open, with many &#8220;stores&#8221; and multiple ways of finding and buying apps, I&#8217;d welcome Flash-built iPhone apps with open arms: the more the merrier. As it is, though, I worry a bit about the flood of muck as every Flash developer (over a million by Adobe&#8217;s count: <strong>A MILLION!</strong>) with a back catalogue of content tries to get their old code into the App Store.</p>
<p>Some obvious predictions:</p>
<ul>
<li>We&#8217;ll see more than a few Flash component libraries that emulate UIKit controls</li>
<li>Apple will unofficially delay or reject Flash-built apps for the first while until/unless Adobe and Apple come to some kind of understanding (<a href="http://www.readwriteweb.com/archives/why_is_apple_rejecting_phonegap-built_iphone_apps.php">see the issues that PhoneGap apps have had in the past</a>, and that uses all native SDKs!).</li>
<li>Flash developers will find it more difficult than they expect to get their old code working well on the iPhone</li>
<li>Many iPhone programming contracts will be lost as clients decide (correctly or incorrectly) that they can do their iPhone project in-house with Flash</li>
</ul>
<p>Still, I have to admit I personally can&#8217;t wait to get my hands on the public beta of Flash CS5. I enjoy working with Flash and ActionScript.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/10/11/flash-and-iphone/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Another UITabBarController change from 2.x to 3.0</title>
		<link>http://www.bunnyhero.org/2009/07/22/another-uitabbarcontroller-change-from-2-x-to-3-0/</link>
		<comments>http://www.bunnyhero.org/2009/07/22/another-uitabbarcontroller-change-from-2-x-to-3-0/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 23:20:33 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone OS 3.0]]></category>
		<category><![CDATA[UITabBarController]]></category>
		<category><![CDATA[UITabBarControllerDelegate]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=222</guid>
		<description><![CDATA[Or actually with UITabBarControllerDelegate, and specifically, with the method tabBarController:didSelectViewController:. According to the docs, the differences: OS called only when tab changes? called when changedprogrammatically? before OS 3.0 YES YES OS 3.0 and later NO NO If you are writing code that runs on both 2.x and 3.0 that needs to get tricky with tabs, these changes are a nuisance. Even more infuriating is that the Apple documentation isn&#8217;t complete. The section ends with the sentence fragment &#8220;If you are implementing&#8230;.&#8221; Yes? If I am implementing what? And what do I do if I am? Yes, I&#8217;ve already reported documentation error. No response though. My guess is they&#8217;ll just remove the sentence fragment instead of expanding on it :( [edited: I made a mistake in the table the first time I posted this. Should be fixed now.]]]></description>
			<content:encoded><![CDATA[<p>Or actually with <strong>UITabBarControllerDelegate</strong>, and specifically, with the method <a href="http://developer.apple.com/IPhone/library/documentation/UIKit/Reference/UITabBarControllerDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITabBarControllerDelegate/tabBarController:didSelectViewController:">tabBarController:didSelectViewController:</a>.</p>
<p>According to the docs, the differences:</p>
<table border="1">
<tr>
<th>OS</th>
<th>called only when<br /> tab changes?</th>
<th>called when changed<br />programmatically?</th>
</tr>
<tr>
<td>before OS 3.0</td>
<td><em>YES</em></td>
<td><em>YES</em></td>
</tr>
<tr>
<td>OS 3.0 and later</td>
<td><em>NO</em></td>
<td><em>NO</em></td>
</tr>
</table>
<p>If you are writing code that runs on both 2.x and 3.0 that needs to get tricky with tabs, these changes are a nuisance.</p>
<p>Even more infuriating is that the Apple documentation isn&#8217;t complete. The section ends with the sentence fragment &#8220;If you are implementing&#8230;.&#8221; Yes? If I am implementing <em>what</em>? And what do I do if I am?</p>
<p>Yes, I&#8217;ve already reported documentation error. No response though. My guess is they&#8217;ll just remove the sentence fragment instead of expanding on it :(</p>
<p>[edited: I made a mistake in the table the first time I posted this. Should be fixed now.]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/07/22/another-uitabbarcontroller-change-from-2-x-to-3-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Approved!</title>
		<link>http://www.bunnyhero.org/2009/07/11/approved/</link>
		<comments>http://www.bunnyhero.org/2009/07/11/approved/#comments</comments>
		<pubDate>Sat, 11 Jul 2009 18:21:54 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=214</guid>
		<description><![CDATA[I forgot to mention that my apps (two versions of the same app: a free, ad-supported one, and a 99-cent ad-free version) were approved this past week on the iPhone App Store! Please check out My Monkey. Time from submission to approval: 13 days. It&#8217;s a simple app, an Objective-C port of my Flash monkey widget. I added support for multitouch, the accelerometer and custom image backgrounds chosen from the user&#8217;s photo library. It was a pretty straightforward port. The main thing I had to get used to again (coming from ActionScript) was the lack of automatic garbage collection. I don&#8217;t expect this app to tear up the charts or anything like that :) but mainly as an exercise in learning iPhone programming and the whole process from code to distribution.]]></description>
			<content:encoded><![CDATA[<p>I forgot to mention that my apps (two versions of the same app: a free, ad-supported one, and a 99-cent ad-free version) were approved this past week on the iPhone App Store!</p>
<p>Please check out <a href="http://bunnyherolabs.com/iphone/mymonkey/"><strong>My Monkey</strong></a>.</p>
<p>Time from submission to approval: 13 days.</p>
<p>It&#8217;s a simple app, an Objective-C port of my <a href="http://bunnyherolabs.com/adopt/customize.php?mc=monkey.swf">Flash monkey widget</a>. I added support for multitouch, the accelerometer and custom image backgrounds chosen from the user&#8217;s photo library.</p>
<p>It was a pretty straightforward port. The main thing I had to get used to again (coming from ActionScript) was the lack of automatic garbage collection.</p>
<p>I don&#8217;t expect this app to tear up the charts or anything like that :) but mainly as an exercise in learning iPhone programming and the whole process from code to distribution.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/07/11/approved/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
