<?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>Dr. Touch</title>
	<atom:link href="http://www.drobnik.com/touch/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.drobnik.com/touch</link>
	<description>Bitching and Stiching iPhone Apps (almost) since 1974</description>
	<lastBuildDate>Sat, 20 Mar 2010 17:09:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Dr. Touch #15 &#8211; &#8220;Sex App Transmittable Diseases&#8221;</title>
		<link>http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/</link>
		<comments>http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 17:09:46 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2259</guid>
		<description><![CDATA[With the sex apps removed Apple does not think we need protection any more. And lots more iPad-News.
Show notes (aka my script) after the break.



Prior to the US launch of the iPad on April 3rd, we see that Apple apparently created 20 eBook-related categories that Apple created specifically for the iBook store. Below these there are [...]]]></description>
			<content:encoded><![CDATA[<p>With the sex apps removed Apple does not think we need protection any more. And lots more iPad-News.</p>

<p>Show notes (aka my script) after the break.</p>
<p><span id="more-2259"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Prior to the US launch of the iPad on April 3rd, we see that Apple apparently created 20 eBook-related categories that Apple created specifically for the iBook store. Below these there are 150 sub-categories for a great variety of book categories ranging from cookbooks to erotic novels. This was uncovered by Busted Loop a company based in San Francisco who was dissecting data that Apple gives to their enterprise customers. Busted Loop slices and dices this data for their AppSlice project which aims to help customers find good apps better. Well in any case they will gain some publicity from this stunt <a href="http://www.forbes.com/2010/03/10/apple-busted-loop-technology-business-intelligence-ipad.html">getting Forbes to report</a> on their findings.</p>
<p>Personally I hope that the iBook-Store will allow for anybody to publish eBooks, this flood of single-book-apps is really something that gets on my nerves. Barnes &amp; Noble has acknowledged that the have plans to create a competing eBook store. They already have a <a href="http://itunes.apple.com/us/app/b-n-ereader/id320915544?mt=8">B&amp;N reader app</a> on the app store, but plans are to also make a new <a href="http://www.macrumors.com/2010/03/11/barnes-and-noble-officially-acknowledges-plans-for-ipad-ereader-application/">iPad-specific app</a> that&#8217;s a shop for books, magazines and newspapers.</p>
<p>The new beta 4 version of SDK 3.2 <a href="http://9to5mac.com/long-press-3tap-iphone-gestures-435983467">brings some minor changes</a>. The buttons for video chat that previously caused speculation have been removed. Also there are new gestures supported by the new gesture recognizers which will make detecting of certain gestures  much easier. Apparently the gesture descriptions are now in plists, possibly to allow your own gestures to be configured in the future. Currently you still have to program your gestures yourself with the touchesBegan, Moved, Ended and Cancelled methods. Having this detection built-in will make gesture implementation really simple.</p>
<p>And actually beta 5 of the SDK 3.2 has been released only 8 days after beta 4, a departure from the previous bi-weekly release schedule that tells us that the final version is getting close. With April 3rd set as first availability date of the iPad that&#8217;s probably going to be the most likely release date for the SDK as well.</p>
<p>Shortly after the beginning of iPad preordering in the US, a company claimed to have &#8220;cracked the code&#8221; of order numbers arriving at an estimate of about 50,000 iPads ordered in the first 2 hours. All they did was basically subtract order numbers. In any case we can assume that many iPhone developers are excited to get an iPad into their fingers. Us Europeans still have to wait a couple of months. Most likely because there is a part shortage that causes a bottleneck for outside of the US. The number was later revised to 91,000 within the first 6 hours. Well, without any information from Apple themselves all these statements are nothing but hot air. It&#8217;s stating the obvious that the iPad is flying off the virtual shelves faster than Apple can produce them.</p>
<p>Apple has been criticized for having the batteries of newer devices not user-servicable which causes a minor hassle every few years when you want to get your battery back to it&#8217;s original capacity. In the case of the iPad Apple also does something unheard of. For 100 Dollars they <a href="http://images.apple.com/support/ipad/service/battery/">will not only replace your iPad&#8217;s battery</a> with a new one. Instead you get a brand new iPad within one week. Now that&#8217;s cool, so battery replacement does not just recharge you, it fully rejuvenates your device. Naturally there is a clause that this offer expires as soon as you pour liquid over the iPad or have somebody unauthorized open it. But I think that&#8217;s a great idea, especially since Steve Jobs keeps telling us that all the latest Apple products are &#8220;highly recyclable&#8221;.</p>
<p>In an interesting move Apple has banned any kind of protective film from their stores. This includes adhesive films as well as cases that come with a screen protector. As usual we don&#8217;t know why, but I guess the reasons are pretty obvious:</p>
<ul>
<li>the iPhone&#8217;s screen is made of glass which is way more durable than other devices screens. Thus the sale of such films conveys the impression that the screens are in need of protection just like those other devices. An emotion that Apple does not want users to have.</li>
<li>actually I&#8217;ve been using my iPhone 3GS without a film ever since I got it and I never have any problem with smudges because of the oleophobic coating. Instead it feels kind of soft and valuable. Apple being interested in maximizing the user experience on all senses probably just wants to get users to experience the touch interface more fully.</li>
<li>It&#8217;s just like sex where you have much more of an experience if you get rid of the condom. Well, now that the app store is cleaned up, we no longer have to fear that we could catch a Sex App Transmittable Disease.</li>
</ul>
<p>Speaking of accessories: it appears that accessories for the iPad will be even harder to come by than the iPad itself. People see the availability dates slip quite a bit. Now we can speculate that this means that there are way more iPad accessories being sold than iPads itself, thus outpacing supply. Seems too many people want the keyboard dock, the VGA adapter cable for presentations or the SD-Card reader adapter. This tells me that more people are seeing the iPad as a productivity platform than just an eBook reader or surf pad.</p>
<p>Apple has <a href="http://developer.apple.com/iphone/news/archives/2010/march/#scheduleprice">introduced a new feature</a> in iTunes Connect that allows you to schedule price tier changes as well as availability dates of new or updated apps. So you no longer have to guess when a new price tier will come into effect, but you can actually plan a staged approach with a low price introduction going to a higher price after some time. Very useful stuff!</p>
<p>PayPal has released version 2 of their app. It now includes Bump technology to bump money between two PayPal users via bumping together their iPhones. This is interesting for us developers because there is an API by Bump to allow you to add bumping to your apps as well. They claim it&#8217;s just 10 lines of code to establish a secure channel between two devices. You know, to have two devices communicate you have multiple possibilities: peer-to-peer bluetooth (if both have bluetooth enabled), WiFi (if both are on the same network) and now Bump. Because Bump goes via any Internet connection you have they can match up two devices regardless of the state of WiFi or Bluetooth. So it&#8217;s not just more convenient for users, it&#8217;s also a cool method. Have a look at their API if you would like to use Bumping in your apps as well.</p>
<p>Right when the preordering for the iPad started Apple updated the iPad product page with some additional details which we did not know about previously.</p>
<ul>
<li>The previously unidentified small button on the right side above the volume control has become a screen rotation lock button. That&#8217;s great if you want to read something in bed on your side.</li>
<li>The iBooks app which will be downloadable from the app store will support the widely used ePub format. You can create such eBooks with tools like Adobe Illustrator. Also you will be able to download any ePub file, put it into iTunes and then synch it to your iPad for reading there.</li>
<li>The iPad will work with ANY bluetooth keyboard. So if you think that the keyboard dock looks weird then you just put a regular Apple bluetooth keyboard in your backpack. Then you won&#8217;t just have a full-size keyboard on screen. You&#8217;ll actually HAVE a full-size keyboard with you.</li>
<li>The iPad will support file-sharing and file associations. You will be able to associate specific apps with their file extensions and if you get an e-mail with such a file you will be able to open the app for it. Also it appears that each app has sort of a public folder that you can see in your Finder as long as the iPad is docked.</li>
<li>The 3G iPad will indeed have built-in GPS. CoreLocation will work on both the WiFi and 3G models, but for the WiFi ones it will only use the SkyHook service to locate the user. So you still get to use location-based services if you never leave the home with your WiFi iPad.</li>
<li>Assistance technology VoiceOver on the iPad will be able to read to you any page, apparently in all 21 supported languages. So this could also turn any eBook into an AudioBook.</li>
<li>Besides of H.264 and Quicktime, the iPad will also natively play motion JPEG files in AVI containers up to 720p. This is probably necessary because it&#8217;s still a video format widely used by still cameras. This container is basically just regular individually compressed JPEG files and uncompressed PCM audio.</li>
<li>Safari on iPad will allow you to play HTML5 video in full screen mode via double-tap.</li>
<li>Webviews now support auto-recognition of addresses. Previously they could only recognize URLs and phone numbers, not addresses as well which apparently open the Maps app when tapped.</li>
<li>We now know how the optional SD-Card reader looks like. It&#8217;s a small white donge, a little larger than an SD-Card and it goes into the dock connector. There is also a second adapter that can act as an intermediary between the iPad and Photo cameras which have USB.</li>
<li>Apple has reaffirmed their claim that you will be able to watch 10 hours of Video on one battery charge.</li>
<li>The mobile iTunes store now also will support browsing, buy and renting movies &#8220;on the go&#8221;. You will be able to watch trailers and when you are ready to rent you will be able to. Also what you downloaded which away from home you can synch back to your iTunes when you get home. Ah and of course the iPad has a &#8220;powerful speaker&#8221; built in, so the updated product page tells us.</li>
<li>The app store will have a special section for apps that support the iPad natively.</li>
<li>The maps app has a new &#8220;terrain&#8221; mode. Don&#8217;t know how it his fundamentally different from map mode.</li>
<li>The calendar now supports setting birthday reminders, something that people have long requested.</li>
<li>The iBooks app has a built-in dictionary. If you don&#8217;t know a word in a book you can search for it in the dictionary, in Wikipedia or on the internet.</li>
</ul>
<p>A developer by the name of Tommy Refene hates the app store and thus thought it would be an interesting  experiment to keep raising the price for his app Zits &amp; Pimples, where you pop pimples. Refenes five months ago raised the app price to $15, leading to three purchases on the same day. Bringing the price up to $50 allegedly resulted in four sales, while fourteen people are said to have bought the game when the price escalated to $299. One person even bought the game for $400 on the same day it was removed. If you do the math that&#8217;s 4831 Dollars in 5 months.</p>
<p>But Apple would not idly watch. Probably somebody complained to the App store team, as should you if you see another developer trying to trick the system. The mail address is <a href="x-msg://471/appstorenotices@apple.com">appstorenotices@apple.com</a> and is good for all kind of abuse. Now apple has finally reacted and pulled the app. Mr. Refene claims that the real reason was that he used swear words describing the app store when he was standing on the stage of the Game Developer&#8217;s Conference.</p>
<p>But wouldn&#8217;t Apple have pulled ALL his apps if this where the case? I think so. Apple treats everybody the same, but if you try to be a smartass and beat them with their own system then this will happen.</p>
<p>Finally Apple has announced that you can now submit iPad Apps which where made with BETA 5 of the 3.2 SDK. You will get pre-reviewed and receive instructions on what to do to get into the illustrious group of launch titles to be released together with the WiFi iPad on April 3rd.</p>
<p>Do you have any iPad app in the works or adding iPad support to an existing app? If so, why don&#8217;t you mail me? I would like to make a blog post mentioning a couple of apps getting ready. For the post I need from you:</p>
<ul>
<li>a nice photo so that my readers can associate a face with the app</li>
<li>one paragraph describing your app</li>
<li>a screenshot showing the iPad interface in action</li>
<li>one paragraph describing what you felt was the challenge in getting ready for the iPad</li>
</ul>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22+-+http://b2l.me/kpf7g+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;t=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;title=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;title=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;bm_description=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22&amp;link=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;title=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;submitHeadline=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22&amp;submitSummary=With%20the%20sex%20apps%20removed%20Apple%20does%20not%20think%20we%20need%20protection%20any%20more.%20And%20lots%20more%20iPad-News.%0D%0A%0D%0A%0D%0A%0D%0AShow%20notes%20%28aka%20my%20script%29%20after%20the%20break.%0D%0A%0D%0A%5Bad%23dr-touch-inline%5D%0D%0A%0D%0APrior%20to%20the%20US%20launch%20of%20the%20iPad%20on%20April%203rd%2C%20we%20see%20that%20Apple%20apparently%20created%2020%C2%A0eBook-related%20categories%20that%20A&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/&amp;title=Dr.+Touch+%2315+-+%22Sex+App+Transmittable+Diseases%22" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/dr-touch-15-sex-app-transmittable-diseases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.drobnik.com/audio/Dr_Touch%20015%20-%20Sex%20App%20Transmittable%20Diseases.mp3" length="22985342" type="audio/mpeg" />
		</item>
		<item>
		<title>Stuff you learn from reverse-engineering Notes.app</title>
		<link>http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/</link>
		<comments>http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 15:33:08 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2300</guid>
		<description><![CDATA[I&#8217;m adding note taking to iWoman 2.0 and so I was thinking which metaphor would be one that users would understand and like. So I decided to mimic the look and feel of the built-in Notes app.

There where quite a few interesting things I had to learn and figure out and in this article I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m adding note taking to iWoman 2.0 and so I was thinking which metaphor would be one that users would understand and like. So I decided to mimic the look and feel of the built-in Notes app.</p>
<p><img class="alignright size-full wp-image-2305" style="margin-left: 10px; margin-bottom: 10px;" title="Notes in iWoman" src="http://www.drobnik.com/touch/wp-content/uploads/2010/03/Screen-shot-2010-03-20-at-4.30.13-PM.png" alt="" width="248" height="462" /></p>
<p>There where quite a few interesting things I had to learn and figure out and in this article I am going to share them with you. These are techniques that you can use in many other scenarios besides of making your own Notes view controller.</p>
<p>I was clear from the start that I needed to use a UITextView for the editing itself. Notes.app has several specialities that we have to figure out if we want to capture the look.</p>
<ul>
<li>Font is Marker Felt Thin, Size 19.</li>
<li>each line sits on top of a grayish blue horizontal line</li>
<li>the text view has a padding at all sides, something that the standard UITextView does not give us</li>
<li>There is padding at the top, but still the text goes up to the corner</li>
<li>the horizontal lines move together with the text and never end towards the bottom</li>
<li>two static vertical brown lines line up with markings at the top and the bottom</li>
<li>the body of the notes is not just a yellow gradient, but has some structure and speckles</li>
<li>scrolled text disappears behind the images for the top and bottom edge</li>
<li>The text view needs to be dynamically resized when the keyboard appears or disappears to prevent hiding of text.</li>
</ul>
<p>Those where the challenges, in this YouTube video you see my solution and an overview of how I achieved it. More in-depth reasoning you find below.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/6o0e-1WFREM&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/6o0e-1WFREM&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><span id="more-2300"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Setting the font and size for the text view is easy, much harder is to a never-ending sheet with lines to move in synch. My first gut feeling was to simply attach it as a subview to the text view which itself is a descendant of UIScrollView. So it&#8217;s possible to insert views as subviews to it and they will get moved together with the contents of the text. If you want to make sure that you don&#8217;t disturb the interaction with the text simply add it at index 0, that is behind all views that might be subviews of the scroll view.</p>
<p>Though for this case this approach would not work as we cannot set a padding for the text view. So we have to move the frame of the text view that the text is at a nice distance from the edges. If we add the lines view now we see that it gets clipped at the edges of the text view. Not what we had in mind.</p>
<p>I started out with just a screenshot of the Notes.app where I removed some UI elements, but then I discovered that I needed to draw the lines myself and that I had to split it in three: top edge, bottom edge and body of the note. For the body I had a friend remove the lines from the screenshot with Photoshop.</p>
<h3>UITextView is an extended UIScrollView</h3>
<p>Since UITextView is a child of UIScrollView all the scrollview delegate methods are also passed to any delegate you might set. So what I did was to simply implement a scrollViewDidScroll method which gets called every time the text view moves. Then I only need to set a transform for the lines view according to the current contentOffset. Having made sure that the top and bottom edge images are on top of the lines view cause them to go underneath those, so I don&#8217;t need an extra clipping view to make sure the lines don&#8217;t go over the images.</p>

<div class="wp_codebox"><table><tr id="p23007"><td class="code" id="p2300code7"><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>scrollViewDidScroll<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIScrollView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>scrollView
<span style="color: #002200;">&#123;</span>
	CGPoint offset <span style="color: #002200;">=</span> scrollView.contentOffset;
	linesView.transform <span style="color: #002200;">=</span> CGAffineTransformMakeTranslation<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span>, <span style="color: #002200;">-</span>offset.y<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The lines themselves are just regular UIView where I filled in the drawRect to draw horizontal lines, nothing fancy there. Same is true for the second view I have for the vertical lines. I&#8217;ve tried to combine the lines into one view, but there I had the problem when you pull down the text view, the vertical lines would break and a whole would appear at the top. So I settled for two line view: one static for the vertical lines and one moving via transform in tandem with the text view. Obviously both have to be non-opaque and have a transparent background.</p>
<p>The next interesting trick necessary becomes apparent when you actually start editing. The keyboard will cover the lower half of the text view causing text to be hidden. My first idea was to resize it but here you have the option to either guess the animation duration and hight or you google it. I found the optimal solution to be present there, on <a href="http://stackoverflow.com/questions/1951826/move-up-uitoolbar	 ">Stack Overflow</a>.</p>
<h3>Resizing in synch with the Keyboard</h3>
<p>Whenever the keyboard appears or disappears notifications are sent that also contain a dictionary giving you all relevant animation parameters. You can simply take those and your animation will be perfectly synchronized with the movement of the keyboard. Be it a toolbar which you want to move from the bottom us so that it rides on top of the keyboard. Or something simple as changing a text view&#8217;s frame.</p>
<p>So we register for the name:UIKeyboardWillShowNotification and name:UIKeyboardWillHideNotification when our notepad appears on screen and unregister when it disappears.</p>

<div class="wp_codebox"><table><tr id="p23008"><td class="code" id="p2300code8"><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> viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewWillAppear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>liftMainViewWhenKeybordAppears<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span>UIKeyboardWillShowNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>returnMainViewToInitialposition<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> name<span style="color: #002200;">:</span>UIKeyboardWillHideNotification object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> viewWillDisappear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewWillDisappear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/"><span style="color: #400080;">NSNotificationCenter</span></a> defaultCenter<span style="color: #002200;">&#93;</span> removeObserver<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>_textView resignFirstResponder<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Then for the real meat we implement our methods that get called when these events occur.</p>

<div class="wp_codebox"><table><tr id="p23009"><td class="code" id="p2300code9"><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> liftMainViewWhenKeybordAppears<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aNotification<span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a><span style="color: #002200;">*</span> userInfo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aNotification userInfo<span style="color: #002200;">&#93;</span>;
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    CGRect keyboardFrame;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardAnimationCurveUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;animationCurve<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardAnimationDurationUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;animationDuration<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardBoundsUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;keyboardFrame<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> context<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span>animationDuration<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationCurve<span style="color: #002200;">:</span>animationCurve<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.textView setFrame<span style="color: #002200;">:</span>CGRectMake<span style="color: #002200;">&#40;</span>self.textView.frame.origin.x, self.textView.frame.origin.y,
        self.textView.frame.size.width, self.textView.frame.size.height <span style="color: #002200;">-</span> keyboardFrame.size.height <span style="color: #002200;">+</span> <span style="color: #2400d9;">5.0</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> returnMainViewToInitialposition<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span style="color: #400080;">NSNotification</span></a><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aNotification<span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a><span style="color: #002200;">*</span> userInfo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>aNotification userInfo<span style="color: #002200;">&#93;</span>;
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    CGRect keyboardFrame;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardAnimationCurveUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;animationCurve<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardAnimationDurationUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;animationDuration<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>userInfo objectForKey<span style="color: #002200;">:</span>UIKeyboardBoundsUserInfoKey<span style="color: #002200;">&#93;</span> getValue<span style="color: #002200;">:&amp;</span>amp;keyboardFrame<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> context<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span>animationDuration<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView setAnimationCurve<span style="color: #002200;">:</span>animationCurve<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.textView setFrame<span style="color: #002200;">:</span>CGRectMake<span style="color: #002200;">&#40;</span>self.textView.frame.origin.x, self.textView.frame.origin.y,
        self.textView.frame.size.width, self.textView.frame.size.height <span style="color: #002200;">+</span> keyboardFrame.size.height <span style="color: #002200;">-</span> <span style="color: #2400d9;">5.0</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>You can see that we are getting our values for animation curve, duration and the frame of the keyboard from values contained in the dictionary that the iPhone is so friendly to provide together with those notifications. Really cool stuff.</p>
<h3>iPadding</h3>
<p>If you have the textView in full view size then you find that it&#8217;s text is too close for comfort to the edges. Now as a scrollview descendant you might have guessed that setting the contentInset might solve this problem, but it does not for horizontal padding. The problem with insetting left or right is that you increase the contentSize causing horizontal scrolling to become possible. But we only want vertical scrolling to occur. That&#8217;s why we change the frame of the text view such that there is enough space at the left and right.</p>
<p>Padding DOES however work nicely to inset the text from the top. The text view align with the bottom corner of the top edge image. By setting a contentInset for top we can get the spacing that we want, but still be able to have the text go to the very corner of the virtual page.</p>
<p>We&#8217;re almost done, the final challenge appears if you add a couple of lines of text to your notepad. The lines view is not yet resized and so the lines just stop.</p>
<h3>Peeking under UITextView&#8217;s Shirt</h3>
<p>Text views somehow know to dynamically resize the content. So my solution for the resizing problem is to add an observer for changes to the contentSize property of UITextView. This technique is called KVO (key value observing) and you can add such a hook to any object so that every time there is a change some method is informed about it.</p>
<p>So in the loadView, where I am creating my view hierarchy, I have this line to install my KVO hook. I choose to only receive the new value by specifying option NSKeyValueObservingOptionNew. If you add a binary OR with NSKeyValueObservingOptionOld you also get sent the value before the change.</p>

<div class="wp_codebox"><table><tr id="p230010"><td class="code" id="p2300code10"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>_textView addObserver<span style="color: #002200;">:</span>self forKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;contentSize&quot;</span> options<span style="color: #002200;">:</span>NSKeyValueObservingOptionNew context<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>The best way to remove the hook is in dealloc. Removing is necessary because otherwise you get a warning on the console that textview was deallocated with a KVO observer still registered.</p>

<div class="wp_codebox"><table><tr id="p230011"><td class="code" id="p2300code11"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>_textView removeObserver<span style="color: #002200;">:</span>self forKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;contentSize&quot;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>All KVO observing for simple values is done in observeValueForKeyPath, as shown below. You receive a change dictionary containing all the before and after values that you chose to get.</p>

<div class="wp_codebox"><table><tr id="p230012"><td class="code" id="p2300code12"><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> observeValueForKeyPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>keyPath ofObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>object change<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>change context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context
<span style="color: #002200;">&#123;</span>
	CGSize newSize <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>change objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;new&quot;</span><span style="color: #002200;">&#93;</span> CGSizeValue<span style="color: #002200;">&#93;</span>;
&nbsp;
	linesView.frame <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span>linesView.frame.origin.x, linesView.frame.origin.y, newSize.width <span style="color: #002200;">+</span> <span style="color: #2400d9;">124.0</span>, newSize.height <span style="color: #002200;">+</span> <span style="color: #2400d9;">480.0</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Since there is no visible border for the lines view I don&#8217;t need to animate the change. I am making the width and height large enough so that the lines view will aways cover the entire screen even if you drag it up so that the bottom rubberbanding occurs.</p>
<h3>Conclusion</h3>
<p>I&#8217;m not as good as a designer as I am a programmer. If you are like me then it is great for practicing your synthetic skills. By synthetic I mean to find a UI that works and then synthesize it out of what you know. You grow as a skilled programmer by finding out the inherent challenges that you have to figure out so that the whole puzzle and UI experience comes together.</p>
<p>One question left unanswered is if Apple will object to me shamelessly reusing their notepad metaphor. If they reject iWoman 2.0 because of this then it&#8217;s should be not too difficult to get a designer to create the 3 images. Maybe I&#8217;d like pink notepaper for iWoman anyway, what do you think?</p>
<p>I polished the <a href="http://www.drobnik.com/touch/parts-store/">DTNotePadViewController</a> into a component that I can reuse with any kind of app that requires lined note paper. To be able to do so I needed to add a delegation mechanism for and dual mode behavior so that I present it modally for new notes and via navigation controller for editing existing notes. That&#8217;s now here.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Stuff+you+learn+from+reverse-engineering+Notes.app+-+http://b2l.me/kpawh+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;t=Stuff+you+learn+from+reverse-engineering+Notes.app" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;title=Stuff+you+learn+from+reverse-engineering+Notes.app" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;title=Stuff+you+learn+from+reverse-engineering+Notes.app" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;bm_description=Stuff+you+learn+from+reverse-engineering+Notes.app&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Stuff+you+learn+from+reverse-engineering+Notes.app&amp;link=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;title=Stuff+you+learn+from+reverse-engineering+Notes.app" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;submitHeadline=Stuff+you+learn+from+reverse-engineering+Notes.app&amp;submitSummary=I%27m%20adding%20note%20taking%20to%20iWoman%202.0%20and%20so%20I%20was%20thinking%20which%20metaphor%20would%20be%20one%20that%20users%20would%20understand%20and%20like.%20So%20I%20decided%20to%20mimic%20the%20look%20and%20feel%20of%20the%20built-in%20Notes%20app.%0D%0A%0D%0A%0D%0A%0D%0AThere%20where%20quite%20a%20few%20interesting%20things%20I%20had%20to%20learn%20and%20figure%20out%20and%20in%20this%20article%20I%20am%20goi&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/&amp;title=Stuff+you+learn+from+reverse-engineering+Notes.app" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Timing is Everything</title>
		<link>http://www.drobnik.com/touch/2010/03/timing-is-everything/</link>
		<comments>http://www.drobnik.com/touch/2010/03/timing-is-everything/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 08:03:02 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Q&A]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2295</guid>
		<description><![CDATA[zeke817 asks:
Hey guys just wondering how to put a timer in the appdelegate. I need a timer to keep playing on through multiple views instead of just playing on 1 view. Any help apperciated
Using timers is pretty simple. There are plenty examples around and it&#8217;s not difficult to understand. Having said that, I am responding to [...]]]></description>
			<content:encoded><![CDATA[<p>zeke817 asks:</p>
<blockquote><p>Hey guys just wondering how to put a timer in the appdelegate. I need a timer to keep playing on through multiple views instead of just playing on 1 view. Any help apperciated</p></blockquote>
<p>Using timers is pretty simple. There are plenty examples around and it&#8217;s not difficult to understand. Having said that, I am responding to this question for three reasons:</p>
<ol>
<li>my posts on my blog have been pretty scarce recently due to lots of programming for customer projects</li>
<li>I think I should at least document how I am using timers so that I can refer people to this post when the question arises again and again.</li>
<li>Explaining a simple thing to somebody else is the best way to train clarity in teaching.</li>
</ol>
<p>Generally speaking timers are not instantiated but <em>scheduled</em>. The difference is that the SDK/OS takes care of their memory management and we only have to worry about whether or not we want them to fire. So we don&#8217;t need to ever release a timer, instead we <em>invalidate</em> it.</p>
<p><span id="more-2295"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Now your choice is to have a timer fire just once or repeatedly. If you want it ongoing then it&#8217;s wise to have an instance variable defined in the header for saving the address of the NSTimer instance in so that we can command it to invalidate itself once we no longer want it to go on. It it&#8217;s just a one-off thing, then we don&#8217;t need an IVAR.</p>
<p>That means adding this to the header&#8217;s interface description between the curly brackets, a variable named &#8220;timer&#8221; which points (asterisk) to an NSTimer instance.</p>

<div class="wp_codebox"><table><tr id="p229517"><td class="code" id="p2295code17"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/"><span style="color: #400080;">NSTimer</span></a> <span style="color: #002200;">*</span>myTimer;</pre></td></tr></table></div>

<p>Somewhere in our code we want to start the timer. There are two methods of creating a timer, via invocation or target/selector. The second one is easier to understand so it&#8217;s the one I&#8217;ve been using. With it you specify the method that you want to be called back on every time the timer fires.</p>

<div class="wp_codebox"><table><tr id="p229518"><td class="code" id="p2295code18"><pre class="objc" style="font-family:monospace;">myTimer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/"><span style="color: #400080;">NSTimer</span></a> scheduledTimerWithTimeInterval<span style="color: #002200;">:</span><span style="color: #2400d9;">5.0</span> target<span style="color: #002200;">:</span>self
                               selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>timerFired<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> userInfo<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> repeats<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>That creates a timer, that will fire after 5 seconds and then repeatedly every 5 seconds. When it fires it will call timerFired: in the same instance you scheduled it, due to using self. You could also be passing some user data, but we don&#8217;t need that for now, so we pass nil.</p>
<p>Of course we need to provide the timerFired: method as well:</p>

<div class="wp_codebox"><table><tr id="p229519"><td class="code" id="p2295code19"><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> timerFired<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/"><span style="color: #400080;">NSTimer</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>timer
<span style="color: #002200;">&#123;</span>
	NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Tick&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>If you have an ongoing timer the least you should do is to invalidate it in the class dealloc. If you are invalidating it without destroying the instance you should also set your instance variable to nil because invalidating an already invalidated timer causes an exception. But [nil invalidate] is always ignored by objective-C.</p>

<div class="wp_codebox"><table><tr id="p229520"><td class="code" id="p2295code20"><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>dealloc
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>myTimer invalidate<span style="color: #002200;">&#93;</span>, myTimer <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #11740a; font-style: italic;">// other releases</span>
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Having a pointer to the timer allows you to do a couple of useful things with the instance methods that NSTimer provides. You can <em>fire</em> it manually, you can ask it if it <em>isValid</em> or you can <em>invalidate</em> it. Because internally NSTimer works with dates (more precisely: with a time duration in seconds since a reference date) for when it fires and not durations you can also get <em>fireDate</em> or <em>setFireDate</em>.</p>
<p>Now about userInfo, you can put anything in there that you like to have present as data in the timerFired method. If you&#8217;re just scheduling timer events for self, then this is mostly useless as you can access all instance variables anyway. But if you have some calculated data from right before the scheduling that&#8217;s not in an IVAR then you can pass it. Or if you are scheduling the receiver of the timerEvent to be a different object then it has much more usefulness.</p>
<p>Timers are a great invention, especially for achieving repeated calling of a given method. Though when you find yourself creating timers with repeats:NO then you might be better of using performSelector:withObject:afterDelay:, I think this is cleaner especially since another developer usually expects timers to be continuous.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Timing+is+Everything+-+http://b2l.me/ke9b6+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;t=Timing+is+Everything" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/timing-is-everything/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;title=Timing+is+Everything" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;title=Timing+is+Everything" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;bm_description=Timing+is+Everything&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Timing+is+Everything&amp;link=http://www.drobnik.com/touch/2010/03/timing-is-everything/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;title=Timing+is+Everything" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;submitHeadline=Timing+is+Everything&amp;submitSummary=zeke817%20asks%3A%0D%0AHey%20guys%20just%20wondering%20how%20to%20put%20a%20timer%20in%20the%20appdelegate.%20I%20need%20a%20timer%20to%20keep%20playing%20on%20through%20multiple%20views%20instead%20of%20just%20playing%20on%201%20view.%C2%A0Any%20help%20apperciated%0D%0AUsing%20timers%20is%20pretty%20simple.%20There%20are%20plenty%20examples%20around%20and%20it%27s%20not%20difficult%20to%20understand.%20Havin&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/timing-is-everything/&amp;title=Timing+is+Everything" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/timing-is-everything/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Filtering Fun with Predicates</title>
		<link>http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/</link>
		<comments>http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 11:15:33 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2264</guid>
		<description><![CDATA[Being present longer than iPhone OS exists on the Mac platform NSPredicate was only introduced to us iPhone developers in Version 3.0 of the SDK. They have multiple interesting uses, some of which I am going to explore in this article.
You will see how you can filter an array of dictionaries, learn that the same [...]]]></description>
			<content:encoded><![CDATA[<p>Being present longer than iPhone OS exists on the Mac platform NSPredicate was only introduced to us iPhone developers in Version 3.0 of the SDK. They have multiple interesting uses, some of which I am going to explore in this article.</p>
<p>You will see how you can filter an array of dictionaries, learn that the same also works for your own custom classes. Then we&#8217;ll see how to replace convoluted IF trees with simple predicates. We&#8217;ll explore how to use predicates to filter entries of a table view and finally peek into the inner workings of predicates.</p>
<p>Being simple and powerful at the same time it took me 3 hours to write this article. I hope you don&#8217;t give up halfway through it, because I promise it will be a great addition to your skillset as iPhone developer.</p>
<p><span id="more-2264"></span></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>One interesting use of predicates is to filter an array for entries where a specific key matches some criteria. In the following example I am adding four people to an array in the form of individual dictionaries. Then I&#8217;m filtering for all the entries that contain the letter o in lastName.</p>

<div class="wp_codebox"><table><tr id="p226429"><td class="code" id="p2264code29"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>people <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>people addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Oliver&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Drobnik&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>people addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Steve&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Jobs&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>people addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Bill&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Gates&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>people addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Obiwan&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Kenobi&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName CONTAINS[cd] %@&quot;</span>,
				<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;o&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filteredArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>people filteredArrayUsingPredicate<span style="color: #002200;">:</span>predicate<span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, filteredArray<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Note that the [cd] next to the operator like causes it to ignore case and diacritics. Case is obvious, o = O. Diacritics are &#8220;ancillary glyphs added to a letter&#8221;, e.g. ó which is adding an accent to a plain o. With the [d] option o == ò == ö.</p>
<p>In the sample I am creating a new filtered array, but NSMutableArray also has a method to do it in-place. filterUsingPredicate leaves only matching items in the array.</p>
<p>A variety of operators is possible when dealing with string properties:</p>
<ul>
<li>BEGINSWITH</li>
<li>CONTAINS</li>
<li>ENDSWITH</li>
<li>LIKE &#8211; wildcard characters ? for single characters and * for multiple characters</li>
<li>MATCHES &#8211; ICU v3 style regular expression</li>
</ul>
<p>Predicates can be very useful to avoid monstrous IF trees. You can chain multiple predicates with the logical operators AND, OR and NOT. To evaluate an expression on a specific object use the predicate&#8217;s evaluateWithObject method.</p>

<div class="wp_codebox"><table><tr id="p226430"><td class="code" id="p2264code30"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>person <span style="color: #002200;">=</span> 	<span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Steve&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Jobs&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span>
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName ENDSWITH %@ AND lastName BEGINSWITH[c] %@&quot;</span>,
				   <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;eve&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;j&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>predicate evaluateWithObject<span style="color: #002200;">:</span>person<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Is YES, matches&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Now in the above samples we&#8217;ve only been using NSDictionary to old our firstName and lastName properties. A quick experiment shows us if this is also working for our own custom classes. Let&#8217;s create a Person class for this purpose. This only has our two properties plus an overriding description to output useful information and a class method to quickly create a Person instance.</p>
<p><strong>Person.h</strong></p>

<div class="wp_codebox"><table><tr id="p226431"><td class="code" id="p2264code31"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> Person <span style="color: #002200;">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>firstName;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>lastName;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>firstName;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>lastName;
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>Person <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>personWithFirstName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>firstName lastName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>lastName;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>Person.m</strong></p>

<div class="wp_codebox"><table><tr id="p226432"><td class="code" id="p2264code32"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;Person.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> Person
<span style="color: #a61390;">@synthesize</span> firstName, lastName;
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>Person <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>personWithFirstName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>firstName lastName<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>lastName
<span style="color: #002200;">&#123;</span>
	Person <span style="color: #002200;">*</span>person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Person alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
	person.firstName <span style="color: #002200;">=</span> firstName;
	person.lastName <span style="color: #002200;">=</span> lastName;
&nbsp;
	<span style="color: #a61390;">return</span> person;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>description
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&lt;%@ '%@ %@'&gt;&quot;</span>,
			NSStringFromClass<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>,
			firstName,
			lastName<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> dealloc
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>firstName release<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>lastName release<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Now let&#8217;s see if we still get the same result if we do the same filtering of an array, this time with our own Person instances in it.</p>

<div class="wp_codebox"><table><tr id="p226433"><td class="code" id="p2264code33"><pre class="objc" style="font-family:monospace;">Person <span style="color: #002200;">*</span>person1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Oliver&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Drobnik&quot;</span><span style="color: #002200;">&#93;</span>;
Person <span style="color: #002200;">*</span>person2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Steve&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Jobs&quot;</span><span style="color: #002200;">&#93;</span>;
Person <span style="color: #002200;">*</span>person3 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Bill&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Gates&quot;</span><span style="color: #002200;">&#93;</span>;
Person <span style="color: #002200;">*</span>person4 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Obiwan&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Kenobi&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>people <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObjects<span style="color: #002200;">:</span>person1, person2, person3, person4, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName CONTAINS[cd] %@&quot;</span>,
			<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;i&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filteredArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>people filteredArrayUsingPredicate<span style="color: #002200;">:</span>predicate<span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, filteredArray<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Yup! Still works! Now is that cool or what? One obvious use for predicates is to filter the data array in a table view controller to only match the contents of your search box.</p>
<p><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/03/Screen-shot-2010-03-14-at-11.31.04.png"><img src="http://www.drobnik.com/touch/wp-content/uploads/2010/03/Screen-shot-2010-03-14-at-11.31.04.png" alt="" title="Filtering People" width="414" height="770" class="alignnone size-full wp-image-2277" /></a></p>
<p>To try this out we need to do the following:</p>
<ol>
<li>create a new navigation-based iPhone application, WITHOUT CoreData</li>
<li>copy the Person header and implementation files to the new project</li>
<li>replace the RootViewController header and implementation as shown below.</li>
</ol>
<p><strong>RootViewController.h</strong></p>

<div class="wp_codebox"><table><tr id="p226434"><td class="code" id="p2264code34"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> RootViewController <span style="color: #002200;">:</span> UITableViewController &lt;UISearchDisplayDelegate, UISearchBarDelegate&gt;
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>people;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filteredPeople;
&nbsp;
	UISearchDisplayController <span style="color: #002200;">*</span>searchDisplayController;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>people;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filteredPeople;
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> UISearchDisplayController <span style="color: #002200;">*</span>searchDisplayController;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>RootViewController.m</strong></p>

<div class="wp_codebox"><table><tr id="p226435"><td class="code" id="p2264code35"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;RootViewController.h&quot;</span>
<span style="color: #6e371a;">#import &quot;Person.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> RootViewController
<span style="color: #a61390;">@synthesize</span> people, filteredPeople;
<span style="color: #a61390;">@synthesize</span> searchDisplayController;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>searchDisplayController release<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>people release<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>filteredPeople release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad 
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
	self.title <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Search People&quot;</span>;
&nbsp;
	Person <span style="color: #002200;">*</span>person1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Oliver&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Drobnik&quot;</span><span style="color: #002200;">&#93;</span>;
	Person <span style="color: #002200;">*</span>person2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Steve&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Jobs&quot;</span><span style="color: #002200;">&#93;</span>;
	Person <span style="color: #002200;">*</span>person3 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Bill&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Gates&quot;</span><span style="color: #002200;">&#93;</span>;
	Person <span style="color: #002200;">*</span>person4 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>Person personWithFirstName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Obiwan&quot;</span> lastName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Kenobi&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	people <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> alloc<span style="color: #002200;">&#93;</span> initWithObjects<span style="color: #002200;">:</span>person1, person2, person3, person4, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// programmatically set up search bar</span>
	UISearchBar <span style="color: #002200;">*</span>mySearchBar <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISearchBar alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>mySearchBar setScopeButtonTitles<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObjects<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;First&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Last&quot;</span>,<span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
	mySearchBar.delegate <span style="color: #002200;">=</span> self;
	<span style="color: #002200;">&#91;</span>mySearchBar setAutocapitalizationType<span style="color: #002200;">:</span>UITextAutocapitalizationTypeNone<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>mySearchBar sizeToFit<span style="color: #002200;">&#93;</span>;
	self.tableView.tableHeaderView <span style="color: #002200;">=</span> mySearchBar;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// programmatically set up search display controller</span>
	searchDisplayController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISearchDisplayController alloc<span style="color: #002200;">&#93;</span> initWithSearchBar<span style="color: #002200;">:</span>mySearchBar contentsController<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>self setSearchDisplayController<span style="color: #002200;">:</span>searchDisplayController<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>searchDisplayController setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>searchDisplayController setSearchResultsDataSource<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>mySearchBar release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark Table view methods</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView numberOfRowsInSection<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>section 
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>tableView <span style="color: #002200;">==</span> self.searchDisplayController.searchResultsTableView<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self.filteredPeople count<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self.people count<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>UITableViewCell <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UITableView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tableView cellForRowAtIndexPath<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSIndexPath_Class/"><span style="color: #400080;">NSIndexPath</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>indexPath 
<span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #a61390;">static</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>CellIdentifier <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cell&quot;</span>;
&nbsp;
    UITableViewCell <span style="color: #002200;">*</span>cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tableView dequeueReusableCellWithIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>cell <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        cell <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UITableViewCell alloc<span style="color: #002200;">&#93;</span> initWithStyle<span style="color: #002200;">:</span>UITableViewCellStyleDefault reuseIdentifier<span style="color: #002200;">:</span>CellIdentifier<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
	Person <span style="color: #002200;">*</span>person;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>tableView <span style="color: #002200;">==</span> self.searchDisplayController.searchResultsTableView<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
        person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.filteredPeople objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
        person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.people objectAtIndex<span style="color: #002200;">:</span>indexPath.row<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
	cell.textLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@ %@&quot;</span>,
						   person.firstName, person.lastName<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> cell;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark Content Filtering</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>filterContentForSearchText<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>searchText scope<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>scope
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>scope isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;First&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span>
					 <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName CONTAINS[cd] %@&quot;</span>, searchText<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
		predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> predicateWithFormat<span style="color: #002200;">:</span>
					 <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastName CONTAINS[cd] %@&quot;</span>, searchText<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	self.filteredPeople <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>people filteredArrayUsingPredicate<span style="color: #002200;">:</span>predicate<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark UISearchDisplayController Delegate Methods</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>searchDisplayController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISearchDisplayController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>controller 
shouldReloadTableForSearchString<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>searchString
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self filterContentForSearchText<span style="color: #002200;">:</span>searchString scope<span style="color: #002200;">:</span>
	 <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self.searchDisplayController.searchBar scopeButtonTitles<span style="color: #002200;">&#93;</span> 
	  objectAtIndex<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self.searchDisplayController.searchBar selectedScopeButtonIndex<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Return YES to cause the search result table view to be reloaded.</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>searchDisplayController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISearchDisplayController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>controller 
shouldReloadTableForSearchScope<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSInteger<span style="color: #002200;">&#41;</span>searchOption
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self filterContentForSearchText<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self.searchDisplayController.searchBar text<span style="color: #002200;">&#93;</span> scope<span style="color: #002200;">:</span>
	 <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self.searchDisplayController.searchBar scopeButtonTitles<span style="color: #002200;">&#93;</span> 
	  objectAtIndex<span style="color: #002200;">:</span>searchOption<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Return YES to cause the search result table view to be reloaded.</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Adding the search display controller is responsible for most of the additional code in this example. Just getting the filtered people to match our search has become very simple due to NSPredicate as you can see in the filterContentForSearchText method. The two UISearchDisplayController Delegate methods are called whenever you type something in the search box or switch between the scope buttons. In this case I am showing how to switch between searching in first names and last names. </p>
<p>The table view for the search results is actually dynamically created when needed. As it&#8217;s using the same data source and delegate methods as the original table view we need to respond differently based on which table view the methods are being called for. This is the reason for the IF in each of these methods. If we are in the search results we take the filteredPeople array, otherwise we use the original people array.</p>
<p>NSPredicate was only introduced into the iPhone SDKs as of version 3.0, so my guess is that there might a few instances in your code where you could simplify the logic with replacing a big IF tree with a simple predicate. Down the road, they are the only method how you can filter data coming from a fetch in CoreData.</p>
<p>In this article I&#8217;ve only used the predicteWithFormat method to create them. That&#8217;s actually a tremendous shortcut, because internally predicates are themselves consisting of several parts, mostly NSExpression instances. So if you feel that your code has become way too easy to understand by using predicates you can also replace them with the original composition.</p>
<p>Using expressions the general approach is to define a left hand expression and a right hand expression and put these into an NSComparisonPredicate. I&#8217;m just showing this here so that you can appreciate the simplicity of the shortcut method presented earlier.</p>

<div class="wp_codebox"><table><tr id="p226436"><td class="code" id="p2264code36"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/"><span style="color: #400080;">NSExpression</span></a> <span style="color: #002200;">*</span>lhs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/"><span style="color: #400080;">NSExpression</span></a> expressionForKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;firstName&quot;</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/"><span style="color: #400080;">NSExpression</span></a> <span style="color: #002200;">*</span>rhs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/"><span style="color: #400080;">NSExpression</span></a> expressionForConstantValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;i&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span style="color: #400080;">NSPredicate</span></a> <span style="color: #002200;">*</span>predicate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSComparisonPredicate_Class/"><span style="color: #400080;">NSComparisonPredicate</span></a>
				   predicateWithLeftExpression<span style="color: #002200;">:</span>lhs
				   rightExpression<span style="color: #002200;">:</span>rhs
				   modifier<span style="color: #002200;">:</span>NSDirectPredicateModifier
				   type<span style="color: #002200;">:</span>NSContainsPredicateOperatorType
				   options<span style="color: #002200;">:</span>NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// same as: 	</span>
<span style="color: #11740a; font-style: italic;">//NSPredicate *predicate = [NSPredicate predicateWithFormat:@&quot;firstName CONTAINS[cd] %@&quot;, @&quot;i&quot;];</span></pre></td></tr></table></div>

<p>Component predicates are achieved the long way in a similar fashion by using NSCompoundPredicate, but there is no using going into these dark depths when the shortcut is so much more convenient.</p>
<p>Finally another hint without going into details: Predicate Templates. You can define any predicate with $Variables instead of an expression. Then when you need them you can use [template predicateWithSubstitutionVariables:] with a dictionary of values to substitute for the $Variables to prep a predicate ready for use.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Filtering+Fun+with+Predicates+-+http://b2l.me/j2bjm+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;t=Filtering+Fun+with+Predicates" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;title=Filtering+Fun+with+Predicates" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;title=Filtering+Fun+with+Predicates" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;bm_description=Filtering+Fun+with+Predicates&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Filtering+Fun+with+Predicates&amp;link=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;title=Filtering+Fun+with+Predicates" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;submitHeadline=Filtering+Fun+with+Predicates&amp;submitSummary=Being%20present%20longer%20than%20iPhone%20OS%20exists%20on%20the%20Mac%20platform%20NSPredicate%20was%20only%20introduced%20to%20us%20iPhone%20developers%20in%20Version%203.0%20of%20the%20SDK.%20They%20have%20multiple%20interesting%20uses%2C%20some%20of%20which%20I%20am%20going%20to%20explore%20in%20this%20article.%0D%0A%0D%0AYou%20will%20see%20how%20you%20can%20filter%20an%20array%20of%20dictionaries%2C%20lea&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/&amp;title=Filtering+Fun+with+Predicates" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/filtering-fun-with-predicates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Directories: Temp, Cache, Documents</title>
		<link>http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/</link>
		<comments>http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 11:09:24 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2252</guid>
		<description><![CDATA[The first thing to learn when starting to persist data onto the iPhones solid state drive is that all apps have their own sandbox. Contrary to other operating systems where you have a shared documents folder, you have several directories for each individual apps. Now on the iPhone these sandbox directories all get a GUID [...]]]></description>
			<content:encoded><![CDATA[<p>The first thing to learn when starting to persist data onto the iPhones solid state drive is that all apps have their own sandbox. Contrary to other operating systems where you have a shared documents folder, you have several directories for each individual apps. Now on the iPhone these sandbox directories all get a GUID in their name, so you have no way to hardcode or guess the real path they will end up on.</p>
<p>Luckily there is a method of getting the path for those directory, which I wrote about about a year ago: <a href="http://www.drobnik.com/touch/2009/03/getting-standard-paths/">Getting Standard Paths</a>. Today I will elaborate a bit on what I learned since then, it turns out that this is only half the story and as intermediate programmer you will want to use the correct kind of folder for each task.</p>
<p><span id="more-2252"></span></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>You have the following kinds of folders at your disposal:</p>
<ul>
<li>the <strong>app bundle</strong> path when getting non-localized resources that you put in your project</li>
<li>the specific path to a<strong> localized resource</strong> in your app bundle, if your app supports multiple languages</li>
<li>the <strong>documents</strong> folder where you save data that also will get backed up.</li>
<li>the <strong>caches</strong> folder where you save data that will NOT get backed up allowing for faster interaction with iTunes</li>
<li>the <strong>temp</strong> folder, which will get automatically cleared and not backed up</li>
</ul>
<p>The latter two are the ones I heard about only recently when watching a training video by Apple. Before then I was always writing all files into the documents. Now this is fine for regular user files that you also want to be backed up, but not for temporary files or file that you can easily download off the internet again. Those should not be kept in documents as they tend to eat up more and more space and will slow down the user&#8217;s backup via iTunes.</p>
<h3>App Bundle</h3>
<p>A bundle has a corresponding representation in an NSBundle instance which you can retrieve via the NSBundle class method mainBundle. On Mac apps sometimes might also consist of several bundles, but on iPhone we always have a single .app bundle.</p>

<div class="wp_codebox"><table><tr id="p225244"><td class="code" id="p2252code44"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> <span style="color: #002200;">*</span>bundle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>bundlePath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>bundle bundlePath<span style="color: #002200;">&#93;</span>;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Bundle: %@&quot;</span>, bundle<span style="color: #002200;">&#41;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>someFile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>bundlePath stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bla.plist&quot;</span><span style="color: #002200;">&#93;</span>;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;File in Bundle: %@&quot;</span>, someFile<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>This makes use of a string method which takes care of adding an extra slash before the file name if necessary. Now this approach works for files that are not localized, but probably you would want to use the next method, which automatically finds the correct path to use for the currently set locale.</p>
<h3>App Bundle (Localized)</h3>
<p>If you are looking for a specific file, there is a technique where you don&#8217;t have to care if it is localized or not. Or if the user&#8217;s device actually is on a locale that you support.</p>

<div class="wp_codebox"><table><tr id="p225245"><td class="code" id="p2252code45"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> <span style="color: #002200;">*</span>bundle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span>;
&nbsp;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>someFile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>bundle pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bla.plist&quot;</span> ofType<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>someFileToo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>bundle pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bla&quot;</span> ofType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;plist&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;File in Bundle: %@&quot;</span>, someFile<span style="color: #002200;">&#41;</span>;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;File in Bundle: %@&quot;</span>, someFileToo<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>It does not matter if you put the type as nil and the name with extension in the first parameter or if you split it correctly. The second is a bit cleaner, but you get the same result. You don&#8217;t have to worry where this file is or if it&#8217;s localized, you always get a usable path back.</p>
<p>A shortcut method for images is this, which also gets you the correct image from the app bundle.</p>

<div class="wp_codebox"><table><tr id="p225246"><td class="code" id="p2252code46"><pre class="objc" style="font-family:monospace;">UIImage <span style="color: #002200;">*</span>image <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;image.png&quot;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>This method has the added advantage of also caching the image. So it will only go to the file system on the first time you are calling it. On subsequent times it will go to the system cache instead.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>NSPathUtilities</h3>
<p>The app bundle folder is not writable (on non-jailbroken devices). Therefore you need to use a different method if you want to save files. The NSPathUtilites provide a C-function to search for specific standard folders. You don&#8217;t need to worry about adding their header, they are loaded by default.</p>

<div class="wp_codebox"><table><tr id="p225247"><td class="code" id="p2252code47"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>writablePaths <span style="color: #002200;">=</span> NSSearchPathForDirectoriesInDomains<span style="color: #002200;">&#40;</span>NSDocumentDirectory, NSUserDomainMask, <span style="color: #a61390;">YES</span><span style="color: #002200;">&#41;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>documentsPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>writablePaths lastObject<span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>fileInDocuments <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>documentsPath stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;file.plist&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;File: %@&quot;</span>, fileInDocuments<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>To get the path for a folder where you can cache files you simply change what you&#8217;re looking for in NSSearchPathForDirectoriesInDomains. Use this whenever you are saving something to disk that can easily be downloaded again and does not need to be backed up.</p>

<div class="wp_codebox"><table><tr id="p225248"><td class="code" id="p2252code48"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>cachesPath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSSearchPathForDirectoriesInDomains<span style="color: #002200;">&#40;</span>NSCachesDirectory, NSUserDomainMask, <span style="color: #a61390;">YES</span><span style="color: #002200;">&#41;</span> lastObject<span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>cacheFile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>cachesPath stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;file.plist&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cache File: %@&quot;</span>, cacheFile<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>The search function always returns an NSArray, so in the documentation you usually see using the objectAtIndex:0. But personally I prefer to use lastObject instead. I don&#8217;t like objectAtIndex because in theory the resulting array could be empty which would cause an exception accessing the item at index 0. The Caches directory typically resides under <bundle_dir>/Library/Caches.</p>
<p>Finally, we&#8217;ll touch upon temporary files. One might suspect that you could get the perfect temporary location also via NSSearchPathForDirectoriesInDomains. One would be wrong.</p>
<p>For historic reasons the need for a temp directory existed in Unix long before Objective-C. So the way to get the temp directory in our language is crafted on top of an existing Unix method using confstr. It&#8217;s also in NSPathUtilities for your convenience.</p>

<div class="wp_codebox"><table><tr id="p225249"><td class="code" id="p2252code49"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>tmpDirectory <span style="color: #002200;">=</span> NSTemporaryDirectory<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>tmpFile <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tmpDirectory stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;temp.txt&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Temp File:%@&quot;</span>, tmpFile<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>That&#8217;s how you get the Doc, Temp and Caches directories.</p>
<h3>Bonus: Filter Array by Extension</h3>
<p>You can ignore the second and third parameter for NSSearchPathForDirectoriesInDomains. Those are onyl useful on OSX. If you look into the header (by CMD+doubleclicking on the function name) you find that there are a couple of interesting category extensions to NSString, allowing for manipulation of paths. Also one piqued my interest that allows to filter an NSArray for specific extensions.</p>
<p>Say if you have some paths in an array and you want to only get the ones matching certain extensions. Previously I would have looped through the array and put the matching items into a new one. But actually it can be as simple as shown here:</p>

<div class="wp_codebox"><table><tr id="p225250"><td class="code" id="p2252code50"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>someFiles <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObjects<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;1.jpg&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;2.png&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;3.jpg&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;4.txt&quot;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filterTypes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;jpg&quot;</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// without dot</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>filteredFiles <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>someFiles pathsMatchingExtensions<span style="color: #002200;">:</span>filterTypes<span style="color: #002200;">&#93;</span>;
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, filteredFiles<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>This will save me lots of typing in the future.</p>
<h3>Conclusion</h3>
<p>The methods of getting the various paths are not difficult. But the knowledge about what is the correct use case for each is what separates a Cocoa Doodler from a Cocoa Programmer. If you find &#8211; like I did &#8211; that you used to save temporary or cached files in the documents folder then you are highly encouraged to go back in and change to using the appropriate folders instead.</p>
<p>This will make your apps a tiny bit better and backups of your user&#8217;s iPhones a little bit faster.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Directories%3A+Temp%2C+Cache%2C+Documents+-+http://b2l.me/jbcmr+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;t=Directories%3A+Temp%2C+Cache%2C+Documents" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;title=Directories%3A+Temp%2C+Cache%2C+Documents" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;title=Directories%3A+Temp%2C+Cache%2C+Documents" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;bm_description=Directories%3A+Temp%2C+Cache%2C+Documents&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Directories%3A+Temp%2C+Cache%2C+Documents&amp;link=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;title=Directories%3A+Temp%2C+Cache%2C+Documents" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;submitHeadline=Directories%3A+Temp%2C+Cache%2C+Documents&amp;submitSummary=The%20first%20thing%20to%20learn%20when%20starting%20to%20persist%20data%20onto%20the%20iPhones%20solid%20state%20drive%20is%20that%20all%20apps%20have%20their%20own%20sandbox.%20Contrary%20to%20other%20operating%20systems%20where%20you%20have%20a%20shared%20documents%20folder%2C%20you%20have%20several%20directories%20for%20each%20individual%20apps.%20Now%20on%20the%20iPhone%20these%20sandbox%20dire&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/&amp;title=Directories%3A+Temp%2C+Cache%2C+Documents" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/directories-temp-cache-documents/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dr. Touch #014 &#8211; &#8220;Bonjour&#8221;</title>
		<link>http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/</link>
		<comments>http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 19:42:46 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2188</guid>
		<description><![CDATA[The iPhone and Apple News have never been as sexy &#8230; Jean Francois Martin sits in for speechless Oliver and provides a French twist.
This episode is brought to you by:
Dr. Touch&#8217;s Parts Store &#8211; easy to use yet professionally looking components that you can use to spruce up your own apps. Augmented Reality, Calendar Control, [...]]]></description>
			<content:encoded><![CDATA[<p>The iPhone and Apple News have never been as sexy &#8230; Jean Francois Martin sits in for speechless Oliver and provides a French twist.</p>
<p>This episode is brought to you by:</p>
<p>Dr. Touch&#8217;s Parts Store &#8211; easy to use yet professionally looking components that you can use to spruce up your own apps. Augmented Reality, Calendar Control, Pin Lock or Purchase Button are only some examples. You get full source code, no static library crap, and lifetime support by Dr. Touch himself. Check it out today!</p>

<p>The Show Notes (aka Script) below the break&#8230;</p>
<p><span id="more-2188"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p><img title="More..." src="http://www.drobnik.com/touch/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /></p>
<h3>News</h3>
<p>Apple apparently has seen that their recent decision to pull 5000 apps from the store for being &#8220;overtly sexual&#8221; was a bit overreaching. I say &#8220;apparently&#8221; because no public communication has occurred, not even to the maker of on swimwear app, who suddenly <a href="http://www.appleinsider.com/blogs/iphone/10/02/23/apple_quietly_reinstates_swimwear_iphone_application.html">found his app reinstated</a>. The app by the name &#8220;Simply Beach&#8221; is <a href="http://itunes.apple.com/at/app/simply-beach/id335321798?mt=8">available for free</a> and ages 4 and up. So if your taste is for wet and hot, then why not get this app? Even if hot is just by the sun and wet through sea water. The only thing naked on the apps of the simply group is their intent on selling you articles, their apps are catalogs with built in shopping basket.</p>
<p>On association that was key in orchestrating the public opinion against porn on the iTunes is the PTC, the Parents Television Council. The immediately <a href="http://www.parentstv.org/ptc/news/articles/2010/AppleiPhoneUpdate.asp">took favorable note</a> and issued a press release <a href="http://www.parentstv.org/PTC/news/release/2010/0224.asp">applauding Apple&#8217;s action</a>. But they seem to be hard to satisfy, the press release quotes the PTC president Tim Winter:</p>
<blockquote><p>“Apple has taken a positive first step towards eliminating kids’ access to sexually explicit and pornographic content on its product lineup and we applaud the company’s efforts.  Apple has made a responsible move and parents are appreciative of the company’s concern for the well-being of children.”</p></blockquote>
<p>First Step? Seriously? What else does the PTC try to get Apple to do? Ah, right the next day after this applauding press release the PTC issued another one, their new target being filthy TV shows like &#8220;Two and a Half Men&#8221;, &#8220;Gossip Girl&#8221; and &#8220;Family Guy&#8221;. Apple apparently has been buying advertisement slots around those TV shows.</p>
<p>Only in America&#8230;. well, at least none of use are in the TV sitcom business. And thankfully we are not working for Apple, because for these poor people PTC is short for Pain in The Crotch.</p>
<p>Besides of sexy apps Apple also <a href="http://www.appleinsider.com/articles/10/03/04/apple_removes_wi_fi_scanners_minimum_functionality_iphone_apps.html">continues to clean up</a> the app store in other areas. Recent victim of this crusade are several WiFi scanners for aledged use of unpublished APIs to show available WiFi networks. One app that did nothing more than quack got rejected for &#8220;minimal functionality&#8221;.</p>
<p>While we&#8217;re still waiting for the actually availability of the iPad a <a href="http://www.appleinsider.com/articles/10/03/01/apple_ipad_production_hit_by_manufacturing_bottleneck_report.html">new rumor</a> has cropped up claiming that there are production problems. Apple was planning to make 800,000 iPads per Month and now there might only be 300,000. This shortage could lead to initial availability being restricted to the USA. We will see. Maybe I&#8217;ll be buying my first iPad in USA anyway when I attend the Voices that Matter conference in Seattle, end of April.</p>
<p>Also they finally announced availability for the USA, Preorders are possible from March 12th with the WiFi-iPad hitting stores on April 3rd. You will also be able to reserve an iPad and pick it up without having to queue. For other countries they have neither stated the local pricing nor the exact days. Actually initially they announced it in countries like UK and Austria with &#8220;Wi-Fi models shipping in late March. 3G models shipping in April. [..] pricing to be announced.&#8221; But when I checked later, the UK text turned into &#8220;Coming late April&#8221; while the Austrian announcement completely disappeared. An interesting footnote can be found on the US site: &#8220;This device has not yet been authorized as required by the rules of the Federal Communications Commission. This device is not, and may not be, offered for sale or lease, or sold or leased, until authorization is obtained.&#8221;</p>
<p>So there might be several issues plaguing the iPad launch. The don&#8217;t get the hardware due the this rumored shortage, they don&#8217;t get FCC approval because they give the US government agency too little time and maybe they are also worried about currency exchange rates changing too much between now late April to commit to prices.</p>
<p>By the way, somebody wrote an e-mail to sjobs@apple.com asking if the iPad would be able to tether with the iPhone. To which he got a response: No. So if you want or need to be mobile with an iPad you have to wait for the 3G Version. What actually amazes me is not that the answer is No, it&#8217;s that people keep getting a response from this e-mail address. Do we really think that Steve Jobs answers all the e-mails he gets <a href="http://www.9to5mac.com/jobs-swedish-iphone-43609634">on his iPhone</a>? With an outdated firmware version?</p>
<p>According to apple all display issues with the 27&#8243; iMacs have been resolved. You might remember that there where 2 firmware updates targeting the graphics. <a href="http://www.macrumors.com/2010/02/26/apple-claims-display-issues-on-27-inch-imac-have-been-addressed/">Apple told Gizmodo</a>:</p>
<blockquote><p>We&#8217;ve addressed the issues that caused display flickering and yellow tint. Customers concerned that their iMac is affected should contact AppleCare.</p></blockquote>
<p>We always intrigued by the number of people in the financial industry whose sole job seems to be to make fancy calculations out of the few numbers that Apple slips them.</p>
<blockquote><p>In a report to clients issued Friday, Morgan Stanley&#8217;s Katy Huberty offered one of her patented risk-reward snapshots of Apple (AAPL), this one even more optimistic than the last, thanks to what she sees as two new catalysts:</p>
<p>- <strong>The iPad launch in March.</strong> Huberty is anticipating unit sales of 6 million in calendar 2010, considerably higher than the Street&#8217;s consensus of 3-4 million<br />
- <strong>New iPhones in June.</strong> She&#8217;s expecting new models that offer &#8220;both a lower total cost of ownership and new functionality, potentially including gesture-based technology&#8221;</p></blockquote>
<p>Tell me if I am wrong, but didn&#8217;t those people at least partially cause last year&#8217;s economic crisis? So why should be believe one Analyst that predicts a glorious future for Apple? Well, simple really, if you are dependent on the success of the iPhone OS platform then you are willing to give credit to any report that predicts a greatly increasing customer base for all your apps. Millions of new potentials customers?! Let&#8217;s get coding!</p>
<p>Ah, and one other thing. Apple has a track record of generally not doing what it is predicted to be doing. If one thing is certain: we will continue to be amazed.</p>
<p>With all the advances in multi-touch input technology it&#8217;s only a matter of time until we will see a big trackpad as mouse replacement for Macs. The name most likely will be &#8220;Magic Trackpad&#8221; as this was on a recent trademark filing of Apple. It would also go together nicely with the Magic Mouse. <a href="http://gizmodo.com/5481073/what-is-apples-magic-trackpad">Gizmodo speculates</a> that it could either be additional sensors for MacBooks which would could detect if you are typing or gesturing and switch on and off parts of an extra wide trackpad. Or it could be a multi-touch gadget for desktop Macs. Maybe we can see something new in this area as soon as June.</p>
<p>Maybe one day I might be able to navigate around multiple files in Xcode with only gestures. But actually I&#8217;d prefer if Apple invested their innovation in things like automatic code generation or at least realtime syntax checking like Microsoft&#8217;s Visual Studio has it for several years now. Right now I have to frequently hit CMD+B to see my errors.</p>
<p>Apple has relaunched the Mac developer program. Previously you had several choices ranging from free for just Xcode, 500 Dollars for the entry level and 3500 Dollars for the big version. Apple admits that the model they introduced for iPhone developers is more successful and so the made the Mac program more like the iPhone program. So they dropped the price and removed hardware discounts. Now the only thing missing for the revamped program is that Apple starts an app store for Mac apps. Now that would be really something.</p>
<h3>About</h3>
<p>Jean Francois Martin tells us about his love child <a href="http://itunes.apple.com/us/app/ultimate-password-manager/id317837271?mt=8">Ultimate Password Manager</a>, more about it on <a href="http://www.tinysofty.com">tinysofty.com</a>. He also recommends his iPhone Development Blog <a href="http://buildingiphoneapps.blogspot.com/" target="_blank">buildingiphoneapps.blogspot.com</a></p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Dr.+Touch+%23014+-+%22Bonjour%22+-+http://b2l.me/h9tc9+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;t=Dr.+Touch+%23014+-+%22Bonjour%22" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;title=Dr.+Touch+%23014+-+%22Bonjour%22" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;title=Dr.+Touch+%23014+-+%22Bonjour%22" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;bm_description=Dr.+Touch+%23014+-+%22Bonjour%22&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Dr.+Touch+%23014+-+%22Bonjour%22&amp;link=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;title=Dr.+Touch+%23014+-+%22Bonjour%22" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;submitHeadline=Dr.+Touch+%23014+-+%22Bonjour%22&amp;submitSummary=The%20iPhone%20and%20Apple%20News%20have%20never%20been%20as%20sexy%20...%20Jean%20Francois%20Martin%20sits%20in%20for%20speechless%20Oliver%20and%20provides%20a%20French%20twist.%0D%0A%0D%0AThis%20episode%20is%20brought%20to%20you%20by%3A%0D%0A%0D%0ADr.%20Touch%27s%20Parts%20Store%20-%20easy%20to%20use%20yet%20professionally%20looking%20components%20that%20you%20can%20use%20to%20spruce%20up%20your%20own%20apps.%20Augm&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/&amp;title=Dr.+Touch+%23014+-+%22Bonjour%22" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/dr-touch-014-bonjour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.drobnik.com/audio/Dr_Touch%20014%20-%20Bonjour.mp3" length="18352228" type="audio/mpeg" />
		</item>
		<item>
		<title>Not for the Money</title>
		<link>http://www.drobnik.com/touch/2010/03/not-for-the-money/</link>
		<comments>http://www.drobnik.com/touch/2010/03/not-for-the-money/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 09:24:14 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Education]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2231</guid>
		<description><![CDATA[I learned a lesson today regarding happiness and programming. If you are concentrating on a single device and/or a niche of applications then often you feel like you&#8217;re the only one you loves the outcome of your never ending pecking at keys. And if you DO get feedback for your apps then often it&#8217;s only [...]]]></description>
			<content:encoded><![CDATA[<p>I learned a lesson today regarding happiness and programming. If you are concentrating on a single device and/or a niche of applications then often you feel like you&#8217;re the only one you loves the outcome of your never ending pecking at keys. And if you DO get feedback for your apps then often it&#8217;s only a rant in the reviews.</p>
<p>I already told you the story <a href="http://www.drobnik.com/touch/2010/03/speakerclock-1-0/">how SpeakerClock came to be</a>. I did not write if for the money because frankly I did not think that anybody but myself would be using it. That&#8217;s also the reason why I am offering it for FREE initially. I&#8217;d rather get a couple of people to use it and send my feedback than have it sit on a virtual shelf collecting dust. Version 1.1 will be the one where I start charging, I decided. Or maybe the basic features now present will stay free, but some upgrades could be a good InAppPurchase.</p>
<p>I&#8217;m going to have a look at what we can learn about making great apps from an unexpected reaction I received.</p>
<p><span id="more-2231"></span><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>Apple currently has some slides in the iPhone Tech Talk Kickoff presentation of what they think makes a good app. I think I&#8217;ll have to make a poster out of this that I can hang on the wall behind my iMac.</p>
<ul>
<li>Delightful</li>
<li>Innovative</li>
<li>Designed</li>
<li>Integrated</li>
<li>Optimized</li>
<li>Connected</li>
<li>Localized</li>
</ul>
<p>Now I&#8217;ve heard this several times already, but have I really understood it yet? Well, only partially. One thing that I try to do is have as little distractions as possible. Take SpeakerClock again as an example: through gestures I was able to have all settings be achievable through the main screen. Though I forgot about mentioning that you can start and stop the countdown by simply tapping on it. I&#8217;ll have to add this to the already extensive instructions that are on the app&#8217;s about page. Another thing that seems to really help users is that they can send me an e-mail with feature requests quite easily.</p>
<p>Starting from the bottom, Localization is something that I saved for future versions due to my self-imposed time constraint of having to finish the app in a single day. Well, for the about part anyway, since the main functionality of the app does not have any text.</p>
<p>I&#8217;ve not had any ideas regarding the app being connected. Would you want to auto-twitter where and when you have started your speech? Hm&#8230;</p>
<p>Optimization is also only possible for the about table view. I hear that performance on 3G iPhones is not so impressive. I&#8217;ve already made some improvements to DTAboutViewController which should pay off in a future update.</p>
<p>Integration with the iPhone&#8217;s hardware is currently through the touch interface. There might be more features that could be done using onboard hardware.</p>
<p>Design is something that I care to avoid because I don&#8217;t consider myself a good designer. But fortunately for the app there is next to no design necessary. I might increase the size of the traffic light and also the active area of the info button.</p>
<p>I cannot say if you can call SpeakerClock innovative, some happy users seem to think it is. I simply tried to emulate a really existing device, but instead of having buttons and settings to manipulate the time, I opted for touch controls.</p>
<p>But the holy grail of all those items is that your app should be delightful. It should make the user happy to have it and through not getting in the way of his wishes cause feelings of joy. Being the most important of the list it is also the hardest to predict. What do users really want? We can only guess. Possibly to be able to carry out a task in a faster and more intuitive way than they where doing it before having the app on their device.</p>
<p>But after all theory the only way to know if you are on the right track is to engage the user personally and ask for his feedback. I am saying feedback because I mean feedback, NOT reviews. A spontaneous reaction to using your app. What feelings does it produce. Very few people are able to really communicate the level of delight they feel when starting your app. But when forced to think about it they often come up with a list of annoyances that they think you should fix to improve your app. While those are great to continue to improve and polish, they only tell you the facts side of the story. What&#8217;s the emotion?</p>
<p>Now we get to what lesson it is that I learned. Yesterday evening I had the spontaneous idea of contacting the TED office and have them try out my app. I had some emotions that would previously have me NOT do that for fear of negative consequences: What if they object to me mentioning the TED clock as inspiration? Am I unknowingly infringing on their copyrights or trademarks? Will they sue me? What if they don&#8217;t like it? I would be devastated. I would consider my life a total failure&#8230; at least my iPhone programming life &#8230;</p>
<p>Or would I?</p>
<p>One thing I learned previously is that at some stage you have to stop with the &#8220;what if&#8221; questions and just take the leap. A very successful business regimen seems to be: Do first, ask permission later. The worst thing that can happen is that you get a cease and desist letter, like when Ravensburger started to tell developers that they where infringing on Ravensburger&#8217;s rights to the trademark &#8220;Memory&#8221;. Or when Andreas Heck received notice by Winning Moves <a href="http://iphone.derheckser.com/2009/07/01/our-card-games-on-iphone-now-to-be-called-super-trumps/">who told him</a> that he was not legally allowed to use the term &#8220;Top Trumps&#8221; for his games, so he renamed them. It&#8217;s easy to correct if only by removing all instances of a word in your app. Or by reaching a licensing agreement. Any action is better than inaction due to fear of negative consequences. And positive action, that is my lesson, opens the opportunity to result in unforeseeable positive reaction.</p>
<p>Getting back to TED, I did not expect a reaction, or a positive one. But I am not listening to my own teaching at times, I previously DID write about <a href="http://www.drobnik.com/touch/2009/11/though-shalt-not-make-predictions/">the folly of making predictions</a>. Again, I predicted wrong.</p>
<p>To my own delight I found the following in my inbox not even a day after submitting the TED contact form:</p>
<blockquote><p>So cool! We&#8217;re all playing with your app in the TED office. Here&#8217;s<br />
TED&#8217;s June Cohen and Chris Anderson.</p></blockquote>
<p style="padding-left: 30px;"><a href="http://www.drobnik.com/touch/wp-content/uploads/2010/03/TED_using_SpeakerClock.jpg"><img class="alignnone size-full wp-image-2232" title="TEDsters with SpeakerClock" src="http://www.drobnik.com/touch/wp-content/uploads/2010/03/TED_using_SpeakerClock.jpg" alt="" width="500" height="375" /></a></p>
<p>If you didn&#8217;t know, <a href="http://en.wikipedia.org/wiki/Chris_Anderson_(TED)">Chris Anderson</a> is the curator of the TED Conference and <a href="http://en.wikipedia.org/wiki/June_Cohen">June Cohen</a> the Executive Producer of TED Media. Having read up on them on Wikipedia makes me smile even broader. These are people that I would love to shake hands and chat with some day to thank them for the great speeches they keep curating and putting on the TED website. Just today they added <a href="http://blog.ted.com/2010/03/before_avatar_a.php">James Cameron</a>, whom I&#8217;ll watch right after publishing this article.</p>
<p>This is the best kind of reaction that one of your apps can elicit in people. &#8220;So cool&#8221; is code for &#8220;Delight&#8221;. And &#8220;Playing with the app&#8221; suggests that the app invites experimentation and exploration with your senses, touch and visual in this case suggesting that if I did not hit the target of Innovative/Optimized, at least I&#8217;m in the ballpark. Maybe that&#8217;s overanalyzing and reading too much into the TEDsters&#8217; reaction.</p>
<p>In any case their example is a great idea for making a developer happy. Make a photo of yourself using his app and send it to him, be sure to *wink* mention some word that he could infer &#8220;Delight&#8221; from. You can be certain this e-mail/Photo will end up in his trophy case. Because in all likelihood he will consider his programming a form of art and only secondarily be doing it for the money.</p>
<p>That&#8217;s an &#8220;idea worth spreading&#8221;,  developers have emotions too, you know. <img src='http://www.drobnik.com/touch/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Not+for+the+Money+-+http://b2l.me/h49vb+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;t=Not+for+the+Money" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/not-for-the-money/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;title=Not+for+the+Money" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;title=Not+for+the+Money" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;bm_description=Not+for+the+Money&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Not+for+the+Money&amp;link=http://www.drobnik.com/touch/2010/03/not-for-the-money/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;title=Not+for+the+Money" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;submitHeadline=Not+for+the+Money&amp;submitSummary=I%20learned%20a%20lesson%20today%20regarding%20happiness%20and%20programming.%20If%20you%20are%20concentrating%20on%20a%20single%20device%20and%2For%20a%20niche%20of%20applications%20then%20often%20you%20feel%20like%20you%27re%20the%20only%20one%20you%20loves%20the%20outcome%20of%20your%20never%20ending%20pecking%20at%20keys.%20And%20if%20you%20DO%20get%20feedback%20for%20your%20apps%20then%20often%20it%27s%20o&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/not-for-the-money/&amp;title=Not+for+the+Money" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/not-for-the-money/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>iPhone Landscape Stands &#8211; Cheap or DIY</title>
		<link>http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/</link>
		<comments>http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 08:07:44 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2210</guid>
		<description><![CDATA[After having released SpeakerClock, a speech countdown clock, I got a couple of suggestions, one was not about the app itself, but about how you could stand the iphone on it&#8217;s side.
Kevin Jamison: &#8220;Now we just need to come up with a simple little stand similar to the iPod Touch uses to hold it in [...]]]></description>
			<content:encoded><![CDATA[<p>After having released <a href="http://www.drobnik.com/touch/2010/03/speakerclock-1-0/">SpeakerClock</a>, a speech countdown clock, I got a couple of suggestions, one was not about the app itself, but about how you could stand the iphone on it&#8217;s side.</p>
<blockquote><p>Kevin Jamison: &#8220;Now we just need to come up with a simple little stand similar to the iPod Touch uses to hold it in a tilted landscape mode. Maybe rubber coated feet so it won&#8217;t slide if you are using a podium.&#8221;</p></blockquote>
<p>I remembered that every once in a while the blogosphere brought to light yet another clever way of solving such problems. A quick search on Google and YouTube yielded a couple of great solutions. Some that you can purchase , same that you can make yourself at little to no cost.</p>
<p>First let&#8217;s look at the professional solutions which typically cost between $5 and $10. After we&#8217;ve set the benchmark we&#8217;ll explore how we can achieve landscape stability ourselves. Building something useful out of physical things might be a welcome distraction from hours of coding Cocoa. <img src='http://www.drobnik.com/touch/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><span id="more-2210"></span></p>
<h2>Professional Stands</h2>
<h3>MovieWedge</h3>
<p>from <a href="http://www.moviewedge.com" target="_blank">MovieWedge.com</a></p>
<p><object style="height: 344px; width: 425px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/O9C2dvayDZY" /><param name="allowfullscreen" value="true" /><embed style="height: 344px; width: 425px;" type="application/x-shockwave-flash" width="100" height="100" src="http://www.youtube.com/v/O9C2dvayDZY" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Crabble</h3>
<p>from <a href="http://www.seskimo.com" target="_blank">Seskimo</a>:</p>
<blockquote><p>The Crabble is the only wallet-sized stand to offer an easily and continuously adjustable landscape viewing angle, ranging from 45 to 90 degrees, and, with its rubber claws, it is the only wallet-sized stand to give you that grip.</p></blockquote>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/Sn24msMUh5Y&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/Sn24msMUh5Y&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>GoGoStand</h3>
<p>from <a href="http://www.gogostand.com/" target="_blank">GoGoStand</a>:</p>
<blockquote><p>The GoGoStand is a plastic folding stand that you can tuck away in your wallet for quick access whenever you need to prop up your phone or gadget. This stand was designed for all generations of iPhones and iPod Touches, but also works with many other phones including the Android G1, Droid, Palm Pre and more.</p></blockquote>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="853" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/T0CWUZaRpss&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="853" height="505" src="http://www.youtube.com/v/T0CWUZaRpss&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Travel Stand</h3>
<p>from <a href="http://www.griffintechnology.com/products/travel-stand">Griffin Technology:</a></p>
<blockquote><p>Travel Stand flips open to safely hold your iPhone or iPod touch in landscape mode for comfortable, hands-free viewing of your movies, videos, music, photos and more. When the show&#8217;s over, wind your earphones around the included cord wrap and flip the Travel Stand closed. Compact enough to slip into your pocket, Travel Stand is the perfect blend of stand and storage.</p></blockquote>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/RmIZVFI0n8Y&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/RmIZVFI0n8Y&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h2>Do it Yourself</h2>
<h3>Paperclip</h3>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/nmgTKDrheYs&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/nmgTKDrheYs&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Mini-DV Tape Box</h3>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/6Mj3s4ONvLY&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/6Mj3s4ONvLY&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>LEGOs</h3>
<p>The maker made the <a href="https://docs.google.com/uc?id=0B7EVxRLTqlLgZDM1YWYxN2YtMTkwMC00NmU1LTgwNzktZmIwMzc0MzBlOTYw&amp;export=download&amp;hl=en">building instructions</a> available at my request.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/0U_8QxOQqIw&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/0U_8QxOQqIw&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Paper</h3>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/y578-Ptte4o&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/y578-Ptte4o&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>$100 Bill</h3>
<p>Same folding technique as the paper version, by Enrique Pardo.</p>
<p><object style="height: 344px; width: 425px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/KU36zTVkOTY" /><param name="allowfullscreen" value="true" /><embed style="height: 344px; width: 425px;" type="application/x-shockwave-flash" width="100" height="100" src="http://www.youtube.com/v/KU36zTVkOTY" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Laser-Cut Acrylic</h3>
<p><a href="http://blog.makezine.com/archive/2007/09/how_to_make_an_iphone_sta.html">Make Magazine</a> has the guide, all you need is access to a laser cutter&#8230;</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/Nz7bd3LmLBk&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/Nz7bd3LmLBk&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Credit Card</h3>
<p>All you need are a pair of scissors, some tape and an expired credit card. By Rod Porterfield.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/a_l3mEkJOls&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/a_l3mEkJOls&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Cardboard Sleeve</h3>
<p>A cup sleeve that you would get free with coffee at &#8211; say &#8211; a Starbucks.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/OSpStu9DSsE&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/OSpStu9DSsE&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Paper Cup</h3>
<p>A dixie cup with optional cancer society rubber wristband for additional grip.</p>
<p><object style="height: 344px; width: 425px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/_bAeYZ85tAU" /><param name="allowfullscreen" value="true" /><embed style="height: 344px; width: 425px;" type="application/x-shockwave-flash" width="100" height="100" src="http://www.youtube.com/v/_bAeYZ85tAU" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Business Card</h3>
<p>By far the easiest, most spontaneous possibility, no tools required.</p>
<p><object style="height: 344px; width: 425px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://www.youtube.com/v/xcylArGSeHE" /><param name="allowfullscreen" value="true" /><embed style="height: 344px; width: 425px;" type="application/x-shockwave-flash" width="100" height="100" src="http://www.youtube.com/v/xcylArGSeHE" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h2>Conclusion</h2>
<p>Having reviewed quite a few ideas that other people had for either sellable products or DIY options I think that I would go for a solution that I could carry amongst my credit cards. There the GoGoStand looks to me the best professional solution even though the media is hyping the MovieWedge. But I don&#8217;t see that fitting into my wallet.</p>
<p>Amongst the DIY it depends if you have time and tools at hand. The variant that has the most likelyhood of being portable is one using nothing but a business card. You don&#8217;t need any tools for it and the folding necessary is easier to remember than for the bill or paper versions.</p>
<p>Please comment below what you&#8217;re using or if you found a version that I have not covered.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=iPhone+Landscape+Stands+-+Cheap+or+DIY+-+http://b2l.me/hzt6e+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;t=iPhone+Landscape+Stands+-+Cheap+or+DIY" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;title=iPhone+Landscape+Stands+-+Cheap+or+DIY" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;title=iPhone+Landscape+Stands+-+Cheap+or+DIY" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;bm_description=iPhone+Landscape+Stands+-+Cheap+or+DIY&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=iPhone+Landscape+Stands+-+Cheap+or+DIY&amp;link=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;title=iPhone+Landscape+Stands+-+Cheap+or+DIY" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;submitHeadline=iPhone+Landscape+Stands+-+Cheap+or+DIY&amp;submitSummary=After%20having%20released%20SpeakerClock%2C%20a%20speech%20countdown%20clock%2C%20I%20got%20a%20couple%20of%20suggestions%2C%20one%20was%20not%20about%20the%20app%20itself%2C%20but%20about%20how%20you%20could%20stand%20the%20iphone%20on%20it%27s%20side.%0D%0AKevin%20Jamison%3A%20%22Now%20we%20just%20need%20to%20come%20up%20with%20a%20simple%20little%20stand%20similar%20to%20the%20iPod%20Touch%20uses%20to%20hold%20it%20in%20a&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/&amp;title=iPhone+Landscape+Stands+-+Cheap+or+DIY" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/iphone-landscape-stands/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SpeakerClock 1.0</title>
		<link>http://www.drobnik.com/touch/2010/03/speakerclock-1-0/</link>
		<comments>http://www.drobnik.com/touch/2010/03/speakerclock-1-0/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 07:11:34 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2185</guid>
		<description><![CDATA[I like to watch the TED Talks, it&#8217;s always something novel and instructive and makes me believe that the world is generally moving towards a brighter future led by a handful of rather bright fellows.
Now one thing these guys do extremely well is to give a TALK. Through experimentation it was found that at that [...]]]></description>
			<content:encoded><![CDATA[<p>I like to watch the <a href="http://www.ted.com/">TED Talks</a>, it&#8217;s always something novel and instructive and makes me believe that the world is generally moving towards a brighter future led by a handful of rather bright fellows.</p>
<p>Now one thing these guys do extremely well is to give a TALK. Through experimentation <a href="http://features.bizmore.com/interview/how-to-present-like-a-ted-presenter">it was found</a> that at that length the speaker is forced to condense his message and be as clear as possible to get his point across. This constraint is enforced by the famous TED <a href="http://blog.ted.com/2009/02/speakers_eye_vi.php">speaker LED clock</a>. (It&#8217;s actually a countdown and not a clock, but people seem to prefer using the word &#8220;clock&#8221; over &#8220;countdown&#8221;)</p>
<p>This is a countdown at the edge of the stage which at a glance shows you what your remaining speaking time is. Also there is a traffic light of sorts. Shortly before the end of the time a green light switches to yellow to signal that you have to start wrapping up your message. Red means that it&#8217;s time for the closing remarks.</p>
<p>Obviously there are <a href="http://tymtek.com/">dedicated devices</a> out there which aim to fill exactly the same need of visualizing a speakers time constraint. And of course there are a couple of iPhone apps providing this functionality. My second choice of the name of my app was taken by <a href="http://www.inuse.se/talktimer/">Talk Timer</a>. Yet another is <a href="http://itunes.apple.com/at/app/speech-timer-free/id303623657?mt=8">Speech Timer Free</a> which provides the traffic light and the <a href="http://itunes.apple.com/at/app/speech-timer-premium/id299470308?mt=8">Premium</a> version of it even allows for exporting of your speaking log.</p>
<p>I might continue to wish I were a great and inspirational speaker, but in the meantime one thing that I CAN do is make such a countdown clock for iPhone. I just had to do it, because the thought of the clock kept popping up in my head and kept distracting me from other projects.</p>
<p>My goal for SpeakerClock was this:</p>
<ul>
<li>emulate the famous TED clock as closely as possible</li>
<li>use big red LED numbers (for which I had invented <a href="http://www.drobnik.com/touch/2010/02/dtlednumberview/">DTLEDNumberView</a>)</li>
<li>allow for all customization and setting via touch gestures, all on the main screen</li>
<li>use the second page solely to showcase DTAboutViewController</li>
</ul>
<p>Version 1 uses the maximum size possible of the digits that is available in landscape mode. Because of this you can see the digits from several meters away which is necessary if you want to position it so that you can move freely while giving your speech. To maximize the size of the clock I had to move minutes and seconds closer together and wrap the traffic lights underneath.</p>
<p>I made it a special point to finish the app within a single day and so I left out several things which I can put it if there is any interest in this app at all. The art of 1.0 is to concentrate on the required core features and leave some of your brilliant ideas for future versions. Here are some ideas still on my mental drawing board:</p>
<ul>
<li>German localization (and other major languages) &#8211; language is not critical to understand usage of the clock all texts are on the instructions and about pages</li>
<li>Multiple Presets &#8211; might be an idea for a freemium upgrade</li>
<li>Recording of speaking logs, summing up your total speaking time, exporting, sharing &#8230;</li>
</ul>
<p>I made a YouTube video to demonstrate the app:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="505" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/StFC_aM3JMo&amp;hl=en_US&amp;fs=1&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="505" src="http://www.youtube.com/v/StFC_aM3JMo&amp;hl=en_US&amp;fs=1&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>I sent the app to Apple yesterday. SpeakerClock will be available on the app store initially for free to get user feedback.</p>
<p>UPDATE: 2 days after submission SpeakerClock is <a href="http://itunes.apple.com/at/app/speakerclock/id359159149?mt=8">now available on the app store</a>.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=SpeakerClock+1.0+-+http://b2l.me/hs6rf+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;t=SpeakerClock+1.0" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;title=SpeakerClock+1.0" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;title=SpeakerClock+1.0" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;bm_description=SpeakerClock+1.0&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=SpeakerClock+1.0&amp;link=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;title=SpeakerClock+1.0" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;submitHeadline=SpeakerClock+1.0&amp;submitSummary=I%20like%20to%20watch%20the%20TED%20Talks%2C%20it%27s%20always%20something%20novel%20and%20instructive%20and%20makes%20me%20believe%20that%20the%20world%20is%20generally%20moving%20towards%20a%20brighter%20future%20led%20by%20a%20handful%20of%20rather%20bright%20fellows.%0D%0A%0D%0ANow%20one%20thing%20these%20guys%20do%20extremely%20well%20is%20to%20give%20a%20TALK.%20Through%20experimentation%20it%20was%20foun&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/03/speakerclock-1-0/&amp;title=SpeakerClock+1.0" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/03/speakerclock-1-0/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Things I learned implementing my first InAppPurchase</title>
		<link>http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/</link>
		<comments>http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 15:39:23 +0000</pubDate>
		<dc:creator>drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.drobnik.com/touch/?p=2174</guid>
		<description><![CDATA[Yesterday I sent my first app off to Apple containing an InAppPurchase (IAP). It&#8217;s a free app that gives the user an option to pay a dollar for a premium features. That&#8217;s what they call Freemium these days. Free to try, premium to get some more.
The possibility for Freemium was only introduced in October 2009 [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I sent my first app off to Apple containing an InAppPurchase (IAP). It&#8217;s a free app that gives the user an option to pay a dollar for a premium features. That&#8217;s what they call <a href="http://en.wikipedia.org/wiki/Freemium">Freemium</a> these days. Free to try, premium to get some more.</p>
<p>The possibility for Freemium was only introduced <a href="http://developer.apple.com/iphone/news/archives/october2009/">in October 2009</a> when Apple finally gave in to developer&#8217;s wish to be able to do away with those dreaded Lite versions which have a very low conversion rate (about 1%) anyway. Until that time IAPs where only available for paid apps.</p>
<p>After developing on the premium content for about two weeks I hit my first roadblock. You apparently cannot configure an app id for use in a provisioning profile it it is already configured on another developer&#8217;s account.</p>
<p>If you are looking for a full walkthrough, this is not the article to provide that. Troy Brant has the most complete <a href="http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/">IAP Walkthrough</a> on his blog. Instead this is a summary of my mental notes.</p>
<p><span id="more-2174"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-1142183725909145";
google_ad_slot = "4110438702";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<h3>Double App Identifier Trouble</h3>
<p>For sake of simplicity I&#8217;ve been using the wildcard app identifier on all my published apps and did not have any problems with this approach. You only need a unique app identifier for apps that either use push notifications or IAPs. So far my apps did neither, so I was not missing anything.</p>
<p>This problem is actually a global one as a devious competitor would be able to block your change of a wildcard provisioning profile to a unique one quite simply. He would only have to inspect your IPAs as downloaded from iTunes for the app id in the info.plist and try to configure it in his program portal. If successful then his app-id squatting is successful and you are effectively prevented from ever adding IAP or Push to your existing app.</p>
<p>In our case it was our own mistake. My brother-in-law had configured the Identifier in his personal developer account because he thought that necessary. We published the app on the customer&#8217;s account with a wildcard app. It was only when I wanted to configure the new id that I found the problem.</p>
<p>So we contacted Apple Developer Support on multiple levels and heard several times that it is not possible to remove an unused app identifier, but &#8220;thank you for your suggestion, we&#8217;ll consider it for future updates&#8221; (I&#8217;m paraphrasing). So if it were for myself I would have had to submit the app as new with the different identifier. I cannot say more but hint that knowing the right people with the right corporate and parallel interests can even move a seemingly unmovable position.</p>
<h3>Setting up in Program Portal</h3>
<p>I configured the app id and created a development provisioning profile for it. Then I built the app with that to see if it really would work and it did. The second step was to configure the necessary IAP product which is done in iTunes Connect. Apple has improved the process quite a bit, because previously you had to submit an app with IAP only to self-reject it right away to be able to configure products.</p>
<p>After setting up the unique app identifier and enabling it for IAP I was able to configure a simple non-consumable product with price tier 1 and localizations for English and German. At minimum you have to have one language even though you might never display the localized title or description. Also you have to provide a screenshot which will show the reviewer what the IAP is about. This will never be seen by customers. The same is true for the &#8220;Reference Name&#8221; which is also just for your own use.</p>
<p>You have a choice of three variants:</p>
<ul>
<li>non-consumable. Customers can purchase this feature once and download it for free on the same or other devices that use the same iTunes login.</li>
<li>consumable. Those are non-transferable and have to be paid for every time.</li>
<li>subscriptions. Like non-consumables those have to be accessible on all the user&#8217;s devices and also have to be paid for every time.</li>
</ul>
<p>So my freemium update clearly is a non-consumable.</p>
<p>As Product ID you should use the parent app&#8217;s ID and append the reference name of your IAP. For example if the app has ID: com.yourcompany.app, then the IAP should have ID com.yourcompany.app.extrafeature1. Note that there seems to be a separate approval process in place for individual apps and IAP products.</p>
<p>When setting up the IAP product you have to approve it yourself and clear it for sale. Then you also have to decide whether it&#8217;s going to be available to an existing app or wether you will be uploading an app update containing this IAP.</p>
<p>The latter will be your choice if you added the feature code to the app itself and the purchase will just unlock it. The former is your option if the content comes for your server and requires no update to the app itself. Some time may have to pass until the new configuration has been replicated to the distributed servers of the iTunes cloud. But in my case the product was available within 15 minutes or so.</p>
<p>I also had to create a special IAP test user on iTunes Connect. For this I used my gmail address with a +iaptest appended. This allows for creating a new iTunes Connect user without having to create a new e-mail address. Note that before testing IAPs on device you need to log out of your regular iTunes user via the App Store settings pane.</p>
<h3>Nuts &amp; Bolts</h3>
<p>The general program logic you will have to put in place is the following:</p>
<ol>
<li>Your program starts out with your store page disabled while you check if purchases are possible. Parental controls or enterprise settings might have disabled app downloads which at the same time prevents in-app purchases.</li>
<li>Construct a list of IAP product identifiers and send an asynchronous query to Apple&#8217;s server.</li>
<li>After a couple of seconds you get a delegate callback telling you which of the passed IDs are invalid and for the valid ones you get an SKProduct object containing localized title, description, price and a locale to format the price with.</li>
<li>At that point you can enable your store and show the localized products. Apple does not provide their nifty purchase button to you (as seen on the mobile app store), so I had to create <a href="http://www.drobnik.com/touch/2010/02/dr-touchs-purchase-button/">DTPurchaseButton</a> to have a UI that the user feels familiar with.</li>
<li>When the user has expressed his intent of purchase you add a payment transaction to the persistent payment queue. After a couple of seconds an alert view pops up asking for the user&#8217;s confirmation. If you had transferred the app to your device in debug mode then it will mention that it&#8217;s in sandbox mode, i.e. just simulating.</li>
<li>Here the user has a choice of cancelling the purchase or OKing it. In both cases after a couple of more seconds you get a callback informing you of the status of the transaction. Note that the callback also occurs once before the confirmation to show that the transaction has gotten status purchasing.</li>
<li>Dependent on the result you either reset your store UI or enable the purchased item. After you made certain that the feature is available you finish the transaction, because otherwise you will continue to receive the callback every time you set the delegate. This is because the user might have exited before receiving payment confirmation.</li>
<li>It&#8217;s up to you to save the unlock somewhere. If you don&#8217;t worry about piracy then NSUserDefaults is a convenient place. If you do, then an encrypted field in the keychain is your most secure option. In your app you have to show the feature as installed so that the user knows his purchase was successful.</li>
<li>(Optional) On the confirmation callback you get an encrypted transaction receipt which you can save on your server. This enables intra-day tracking of purchases as well as gives you an option to verify the receipt from your server against Apple&#8217;s server and remotely disable the unlock in case of fraud.</li>
</ol>
<p>If a non-consumable IAP product has been purchased before then you get the same callback, but the user gets an additional information that the re-download is not being charged. Finally, if you are listening to Apple&#8217;s recommendation, you will implement a &#8220;Restore Purchases&#8221; button in case the app gets reinstalled on the same or a different device. This button is tied to a simple method of payment queue and will trigger the callback mentioned in 7 for each already purchased product.</p>
<p>I was at first confused about the &#8220;finishing of transactions&#8221;, but you can safely do that as soon as you unlocked the feature. The restore goes into Apple&#8217;s records and finds all previous transactions this user did for this app. You could also rely on re-downloads not being charged, but as soon as you have more than a single IAP this restore button is way more user-friendly. Well, even with just a single IAP you should have the button. It makes the user feel safer knowing that he can restore the value for his hard-spent dollar.</p>
<h3>Tricks of the Trade</h3>
<p>The StoreKit API in itself is very simple to use once you had a couple of unclarity-realted thoughts removed, either by experiment or hearing from somebody with IAP experience. But it has something of a problem that is due to the design with delegate setting and callback methods. To properly use it in your app you are best of creating a singleton shared instance that encapsulates all the unlock-tracking and communicating with StoreKit.</p>
<p>When certain actions occur, like the product list being available, you post notifications to which your view controllers can respond accordingly.  This way you don&#8217;t have to constantly change the delegate or have your app stuck waiting on the app store server to respond.</p>
<p>I put all my store logic into a class I aptly named DTStore. It&#8217;s quite simple really so I added it as a free bonus to DTPurchaseButton which you can get on my <a href="http://www.drobnik.com/touch/parts-store/">Parts Store</a>.</p>
<p>One question I only found the answer to when studying the documentation is how to get the appropriate price to show. You know, you don&#8217;t set a price, but a tier and Apple will give you the appropriate price to show for each store automatically. This lifts a heavy burden off your shoulders as you can never guess what the real price will be fore any of the 96 app stores.</p>
<p>From the documentation I not only learned that the price is there with the correct value, but also that Cocoa gives me methods to format it appropriately for my current locale. Consider the following snipped from DTStore. Knowing that there is a number formatter, a number style NSNumberFormatterCurrencyStyle and a price locale in the SKProduct allows you to do the following.</p>

<div class="wp_codebox"><table><tr id="p217452"><td class="code" id="p2174code52"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>localizedPriceForProductWithSKU<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>sku
<span style="color: #002200;">&#123;</span>
	SKProduct <span style="color: #002200;">*</span>product <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self productForSKU<span style="color: #002200;">:</span>sku<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>product<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/"><span style="color: #400080;">NSNumberFormatter</span></a> <span style="color: #002200;">*</span>numberFormatter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/"><span style="color: #400080;">NSNumberFormatter</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>numberFormatter setFormatterBehavior<span style="color: #002200;">:</span>NSNumberFormatterBehavior10_4<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>numberFormatter setNumberStyle<span style="color: #002200;">:</span>NSNumberFormatterCurrencyStyle<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>numberFormatter setLocale<span style="color: #002200;">:</span>product.priceLocale<span style="color: #002200;">&#93;</span>;
		<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>numberFormatter stringFromNumber<span style="color: #002200;">:</span>product.price<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
		NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Invalid Product ID %@&quot;</span>, sku<span style="color: #002200;">&#41;</span>;
		<span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Until now it had beeb burnt into my brain that I could only format numbers by means of stringWithFormat: but this would not have allowed for this kind of currency formatting. So this is a good piece of code to bookmark should you ever have to format monetary values in the future.</p>
<h3>Conclusion</h3>
<p>If you omit the optional server-side tracking, tighter unlock-security and validation the whole affair can be finished in a single working day, provided that you don&#8217;t have to spend too much time figuring out the intricacies of StoreKit and don&#8217;t want fancy UI work which you&#8217;d have to program or buy first. The StoreKit API in itself is beautiful and simple. It does precisely what it should but it neither provides you with any code for your store user interface or tracking of what purchases you have to unlock.</p>
<p>Generally I have to admit that the process of adding your first freemium content as IAP is far less painful than I previously thought. I guess I&#8217;m going to add this model to many more apps in the future.</p>


<!-- Begin SexyBookmarks Menu Code -->
<div class="sexy-bookmarks sexy-bookmarks-expand sexy-bookmarks-bg-sexy">
<ul class="socials">
		<li class="sexy-twitter">
			<a href="http://twitter.com/home?status=Things+I+learned+implementing+my+first+InAppPurchase+-+http://b2l.me/hm9bz+(via+@dr_touch)" rel="nofollow" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="sexy-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;t=Things+I+learned+implementing+my+first+InAppPurchase" rel="nofollow" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="sexy-technorati">
			<a href="http://technorati.com/faves?add=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/" rel="nofollow" title="Share this on Technorati">Share this on Technorati</a>
		</li>
		<li class="sexy-delicious">
			<a href="http://del.icio.us/post?url=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;title=Things+I+learned+implementing+my+first+InAppPurchase" rel="nofollow" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="sexy-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;title=Things+I+learned+implementing+my+first+InAppPurchase" rel="nofollow" title="Digg this!">Digg this!</a>
		</li>
		<li class="sexy-misterwong">
			<a href="http://www.mister-wong.com/addurl/?bm_url=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;bm_description=Things+I+learned+implementing+my+first+InAppPurchase&amp;plugin=sexybookmarks" rel="nofollow" title="Add this to Mister Wong">Add this to Mister Wong</a>
		</li>
		<li class="sexy-friendfeed">
			<a href="http://www.friendfeed.com/share?title=Things+I+learned+implementing+my+first+InAppPurchase&amp;link=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/" rel="nofollow" title="Share this on FriendFeed">Share this on FriendFeed</a>
		</li>
		<li class="sexy-google">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;title=Things+I+learned+implementing+my+first+InAppPurchase" rel="nofollow" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
		<li class="sexy-yahoobuzz">
			<a href="http://buzz.yahoo.com/submit/?submitUrl=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;submitHeadline=Things+I+learned+implementing+my+first+InAppPurchase&amp;submitSummary=Yesterday%20I%20sent%20my%20first%20app%20off%20to%20Apple%20containing%20an%20InAppPurchase%20%28IAP%29.%20It%27s%20a%20free%20app%20that%20gives%20the%20user%20an%20option%20to%20pay%20a%20dollar%20for%20a%20premium%20features.%20That%27s%20what%20they%20call%20Freemium%20these%20days.%20Free%20to%20try%2C%20premium%20to%20get%20some%20more.%0D%0A%0D%0AThe%20possibility%20for%20Freemium%20was%20only%20introduced%20in&amp;submitCategory=science&amp;submitAssetType=text" rel="nofollow" title="Buzz up!">Buzz up!</a>
		</li>
		<li class="sexy-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/&amp;title=Things+I+learned+implementing+my+first+InAppPurchase" rel="nofollow" title="Stumble upon something good? Share it on StumbleUpon">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
<!-- End SexyBookmarks Menu Code -->

]]></content:encoded>
			<wfw:commentRss>http://www.drobnik.com/touch/2010/02/things-i-learned-implementing-my-first-inapppurchase/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
