<?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>Mundue Blog</title>
	<atom:link href="http://blog.mundue.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mundue.net</link>
	<description>Indie iPhone Development</description>
	<lastBuildDate>Sun, 18 Nov 2012 19:44:05 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Adding scripts to Apple Mail Rules</title>
		<link>http://blog.mundue.net/2012/02/apple-mail-rules-scripts/</link>
		<comments>http://blog.mundue.net/2012/02/apple-mail-rules-scripts/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 22:00:17 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=535</guid>
		<description><![CDATA[I use Apple Mail Rules for many things. They help me organize and flag incoming messages, which I find very useful. Recently however I came across a problem trying to implement a rule which is supposed to run a script as its action. The AppleScript code was never executing. Attempts to seek solutions via Twitter, [...]]]></description>
				<content:encoded><![CDATA[<p>I use Apple Mail Rules for many things. They help me organize and flag incoming messages, which I find very useful. Recently however I came across a problem trying to implement a rule which is supposed to run a script as its action. The AppleScript code was never executing. Attempts to seek solutions via Twitter, StackOverflow, and mailing lists all yielded no working results. I finally got it working, and thought I&#8217;d share how it&#8217;s done.</p>
<p><span id="more-535"></span></p>
<p>If you&#8217;re not familiar with Rules, here a quick explanation. Rules operate on incoming messages and test them against each rule&#8217;s conditions. If conditions are met, the message is subject to perform the rule&#8217;s action. In Mail&#8217;s Preferences pane, you select the Rules icon and click on Add Rule. Give your rule a description (name it, essentially), then define some conditions and actions. The conditions can be logically ANDed (&#8220;all&#8221;) or ORed (&#8220;any&#8221;) together to get the desired results. There&#8217;s a lengthy list of conditions in the popup menu. Options for each condition help narrow it down, for example, the Account condition has a list of all your active accounts. The built-in actions for a rule include moving to a folder, marking it flagged, playing a sound, etc.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="NewImage.png" src="http://blog.mundue.net/wp-content/uploads/2012/02/generalNewImage.png" alt="NewImage" width="600" height="382" border="0" /></p>
<p>One action that I hadn&#8217;t used before was &#8220;Run AppleScript.&#8221; In this case I need to use a script to extract the email address of the sender from a message. Maybe there&#8217;s an easier way, but I decided to try to write a simple script and see what would happen. I&#8217;m no stranger to AppleScript because I was using it before the System 7 rollout over 20 years ago.† So what would such an AppleScript look like? If you look at the Help for using scripts as rule actions, it says to simply select your existing script file from the file chooser. Then it says, &#8220;To see sample scripts for mail, open the AppleScript dictionary for Mail.&#8221; Aha! That should be insightful. Clicking on the link brings up the AppleScipt editor (found in /Applications/Utilities) with the dictionary for Mail. An AppleScript dictionary shows the publicly exposed message suites that Mail supports. This basically defines how you can interact with Mail through Apple Events, the underlying technology behind AppleScript.</p>
<p>But there are no sample scripts. OK, I try the menu item File-&gt;New From Template-&gt;Mail-&gt;Mail Rule Action.scptd, which prompts you for a save location. In my internet search results people mentioned saving such scripts into ~/Library/Mail Scripts. That folder doesn&#8217;t exist, but I created it and saved my file. The script has the thinnest of possible example code to show how you might use it to process each message. Then I added something innocuous to the script, like a beep command, so I could tell if it&#8217;s working or not. Going back to Mail, I selected my new script and saved the rule. To make it even easier, I made the rule&#8217;s condition match any message from a particular account. One way to test rules is to select some message in a mailbox and choose &#8220;Apply Rules&#8221; from the context menu. [NOTE: this will apply ALL the rules for the selected messages, not the one you just created!]</p>
<p>In my case, the rule matched the conditions, but the script didn&#8217;t run. You can add another action in the rule to play a sound (this is different from the beep command in the script) and that action runs, so you know the condition is met. So what&#8217;s the problem? Well, it turns out there&#8217;s a bug in Mail, and when you choose the file in your ~/Library/Mail Scripts folder, it can&#8217;t parse the path name. Instead of inserting /Users/mmartel/Library/Mail Scripts/MyScript.scptd it inserts the friendly ~/Library/Mail Scripts/MyScript.scptd path.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="NewImage.png" src="http://blog.mundue.net/wp-content/uploads/2012/02/generalNewImage1.png" alt="NewImage" width="543" height="95" border="0" /></p>
<p>Now that&#8217;s a real bummer. If you dig a little deeper, you can find out that in Lion the sample Mail scripts are actually in a new folder, in the system Library folder:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="NewImage.png" src="http://blog.mundue.net/wp-content/uploads/2012/02/generalNewImage2.png" alt="NewImage" width="538" height="598" border="0" /></p>
<p>OK, now these are some useful script samples, and if you look here you&#8217;ll find some good examples. But what happens if you try to save your scripts to that folder? Not possible, sorry. That Library folder is restricted in Lion, so you can&#8217;t put your files in there without mucking with permissions. So now what? Can&#8217;t put scripts in my own folders, can&#8217;t put them in the system&#8217;s folders. This isn&#8217;t looking good.</p>
<p>My solution is to put them in a shared folder which I can write to. Such a folder is /Users/Shared/ and if you select a script in there then Mail won&#8217;t need to use the ~ substitution which causes the bug which makes it unable to locate and run the AppleScript. I don&#8217;t know why this process isn&#8217;t better documented. Until then I&#8217;ve filed a bug with Apple and hopefully someday we can again put scripts in our own user folders and have Mail find/execute them.</p>
<p>For the curious among you, here&#8217;s part of my script, which just says the name of the sender of a message that meets the conditions:</p>
<p style="margin: 0.0px 0.0px 0.0px 41.6px; text-indent: -41.6px; font: 12.0px Verdana;"><strong>using terms from</strong> <span style="color: #033efc;"><em>application</em></span> &#8220;Mail&#8221;</p>
<p style="margin: 0.0px 0.0px 0.0px 83.2px; text-indent: -83.2px; font: 12.0px Verdana; color: #033efc;"><span style="color: #000000;"><strong>on</strong> </span><strong>perform mail action with messages</strong><span style="color: #538e13;">theseMessages</span>for rule<span style="color: #538e13;">SaveSender</span></p>
<p style="margin: 0.0px 0.0px 0.0px 124.8px; text-indent: -124.9px; font: 12.0px Verdana;"><strong>tell</strong> <span style="color: #033efc;"><em>application</em></span> &#8220;Mail&#8221;</p>
<p style="margin: 0.0px 0.0px 0.0px 166.5px; text-indent: -166.5px; font: 12.0px Verdana; color: #538e13;"><span style="color: #000000;"><strong>repeat</strong> <strong>with</strong> </span>eachMessage<span style="color: #000000;"> <strong>in</strong> </span>theseMessages</p>
<p style="margin: 0.0px 0.0px 0.0px 208.1px; text-indent: -208.2px; font: 12.0px Verdana;"><strong>set</strong> <span style="color: #538e13;">name_</span> <strong>to</strong> <span style="color: #033efc;"><strong>extract name from</strong></span> <strong>the</strong> <span style="color: #7f38d9;">sender</span> <strong>of</strong> <span style="color: #538e13;">eachMessage</span></p>
<p style="margin: 0.0px 0.0px 0.0px 208.1px; text-indent: -208.2px; font: 12.0px Verdana;"><span style="color: #0235bb;"><strong>do shell script</strong></span> &#8220;say &#8216;Received email from &#8221; &amp; <span style="color: #538e13;">name_</span> &amp; &#8220;&#8216;&#8221;</p>
<p style="margin: 0.0px 0.0px 0.0px 166.5px; text-indent: -166.5px; font: 12.0px Verdana;"><strong>end</strong> <strong>repeat</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 124.8px; text-indent: -124.9px; font: 12.0px Verdana;"><strong>end</strong> <strong>tell</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 83.2px; text-indent: -83.2px; font: 12.0px Verdana; color: #033efc;"><span style="color: #000000;"><strong>end</strong> </span><strong>perform mail action with messages</strong></p>
<p style="margin: 0.0px 0.0px 0.0px 41.6px; text-indent: -41.6px; font: 12.0px Verdana;"><strong>end</strong> <strong>using terms from</strong></p>
<p>The &#8220;do shell script&#8221; is just a way to run bash scripts inline, and from there your imagination is the limit as to what this AppleScript can do. Check out the example scripts mentioned above to find out more about the specific syntax requirements.</p>
<p>I hope you find this useful. I just wish I hadn&#8217;t wasted the better part of a day figuring it out. If you know of better documentation, please let me know where to find it.</p>
<p>&#8212;&#8211;</p>
<p>† Does anybody remember <em>Inside Macintosh: Volume VI</em> or all 1008 pages of <em>Inside Macintosh: Interapplication Communication</em>?</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2012/02/apple-mail-rules-scripts/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using NSOperationQueue for Background Parsing</title>
		<link>http://blog.mundue.net/2011/09/nsoperationqueue-background-parsing/</link>
		<comments>http://blog.mundue.net/2011/09/nsoperationqueue-background-parsing/#comments</comments>
		<pubDate>Sat, 03 Sep 2011 23:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=523</guid>
		<description><![CDATA[Let&#8217;s say you&#8217;re making HTTP requests and handling responses as we described last time. Parsing the results is usually pretty easy, but what happens when you have a large blob of data, be it XML or JSON or whatever? Any lengthly processing on the main thread, more than a couple hundred milliseconds, will introduce a [...]]]></description>
				<content:encoded><![CDATA[<p>Let&#8217;s say you&#8217;re making HTTP requests and handling responses as we <a href="http://blog.mundue.net/2011/07/simple-http-request-handling/">described last time</a>. Parsing the results is usually pretty easy, but what happens when you have a large blob of data, be it XML or JSON or whatever? Any lengthly processing on the main thread, more than a couple hundred milliseconds, will introduce a noticeable hiccup in the UI. Adding a worker thread would help, but perhaps the easiest method is to use the non-blocking NSOperationQueue. With NSOperationQueue you simply package up the work to be done into an NSOperation instance and add it to the queue.</p>
<p><span id="more-523"></span></p>
<p>Your application can create any number of NSOperationQueue objects, but the documentation suggests there is a practical limit to how many operations are executing at any given time. Specifically, adding additional queues does not mean you can execute additional operations. I find that a single queue is usually sufficient. Having access to a global operation queue means you can add, suspend, and cancel operations as needed. Add something like this to ApplicationDidFinishLaunching:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;">// Create the shared operation queue</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;">sharedOperationQueue<span style="color: #000000;"> = [[</span>NSOperationQueuealloc<span style="color: #000000;">] </span>init<span style="color: #000000;">];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><br />
</span></p>
<div>Then you can begin adding operations to the queue. Take the request handler callback we used last time, and modify it slightly, like this:</div>
<div>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #033efc;">id</span> delegate = <span style="color: #033efc;">self</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">myConnectionController* connectionController = [[[myConnectionController alloc] initWithDelegate:delegate</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">selSucceeded:<span style="color: #033efc;">@selector</span>(connectionSucceededWrapper:)</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">selFailed:<span style="color: #033efc;">@selector</span>(connectionFailed:)] autorelease];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"> [</span>myConnectionController startRequestForURL<span style="color: #000000;">:[</span>NSURLURLWithString<span style="color: #000000;">:</span><span style="color: #b12620;">@"http://request.org/somequery.php"</span><span style="color: #000000;">]];</span></p>
<div><span style="color: #000000;"><br />
</span></div>
</div>
<p>Notice all we did was change the selSucceeded selector to connectionSucceededWrapper:. The new wrapper method creates and adds the operation to the queue, as follows:</p>
<div>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #033efc;">void</span>)connectionSucceededWrapper:(<span style="color: #3b95ae;">NSMutableData</span>*)data</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</p>
<p style="font: normal normal normal 11px/normal Menlo; margin: 0px;"><span style="color: #3b95ae;">  NSInvocationOperation<span style="color: #000000;">* theOp = [[</span>NSInvocationOperation alloc<span style="color: #000000;">] </span>initWithTarget<span style="color: #000000;">:</span><span style="color: #033efc;">self</span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #3b95ae;">     selector</span>:<span style="color: #033efc;">@selector</span>(connectionSucceeded:) <span style="color: #3b95ae;">object</span>:data];</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;">  [</span>sharedOperationQueue addOperation<span style="color: #000000;">:theOp];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">
</div>
<div>There&#8217;s no need to change the connectionSucceeded callback. This is presumably where you do the parsing, or any lengthy processing, and probably post notification that the model has changed. Perhaps you are loading thumbnail images and need to cache the image data and notify a table view to refresh a cell. Because the NSOperationQueue operates in a separate thread your UI will not stutter. However, since it executes on another thread, if you need to update any UI elements make sure to use performSelectorOnMainThread: when doing so.</div>
<hr />
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>,</em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/09/nsoperationqueue-background-parsing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Simple HTTP Request Handling</title>
		<link>http://blog.mundue.net/2011/07/simple-http-request-handling/</link>
		<comments>http://blog.mundue.net/2011/07/simple-http-request-handling/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 05:00:57 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Xcode]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=435</guid>
		<description><![CDATA[It&#8217;s common for iPhone apps to need to make HTTP requests and receive results in either JSON or XML format. There are several excellent full-featured tools ( ASIHTTPRequest, RestKit, etc.) to help you with this task, but sometimes all you need is NSURLConnection. NSURLConnection is a simple class that provides easy to use high-level asynchronous [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s common for iPhone apps to need to make HTTP requests and receive results in either JSON or XML format. There are several excellent full-featured tools ( <a href="http://blog.mundue.net/allseeing-i.com/ASIHTTPRequest">ASIHTTPRequest</a>, <a href="http://blog.mundue.net/restkit.org">RestKit</a>, etc.) to help you with this task, but sometimes all you need is NSURLConnection. NSURLConnection is a simple class that provides easy to use high-level asynchronous request/response handling.  I&#8217;ll describe a simple wrapper I&#8217;ve been using to make it easy to handle multiple requests easily.</p>
<p>When using <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html">NSURLConnection</a> there are only a couple of things to deal with. Unless you are using the synchronous version (not recommended) you will typically set up an object, such as your application delegate or a view controller, as a delegate to receive the NSURLConnectionDelegate callbacks. The main delegate message you need to handle are connection:didFailWithError:, connection:didReceiveData:, and connectionDidFinishLoading:.</p>
<p>One potential issue you face here is using a single object as delegate for multiple connections. Then your delegate message handlers will become messy as they attempt to determine which response goes with which request, etc. Now instead consider creating a utility class with just two public methods, like this:</p>
<p><div id="wpshdo_1" class="wp-synhighlighter-outer"><div id="wpshdt_1" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_1"></a><a id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">myConnectionController interface</a></td><td align="right"><a href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_1" class="wp-synhighlighter-inner" style="display: block;"><span class="kw1">@interface</span> myConnectionController <span class="sy0">:</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span class="kw5">NSObject</span></a> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableData_Class/"><span class="kw5">NSMutableData</span></a><span class="sy0">*</span> receivedData;<br />
<span class="br0">&#125;</span><br />
<span class="kw1">@property</span> <span class="br0">&#40;</span>nonatomic, retain<span class="br0">&#41;</span> <span class="kw4">id</span> connectionDelegate;<br />
<span class="kw1">@property</span> <span class="br0">&#40;</span>nonatomic<span class="br0">&#41;</span> <span class="kw4">SEL</span> succeededAction;<br />
<span class="kw1">@property</span> <span class="br0">&#40;</span>nonatomic<span class="br0">&#41;</span> <span class="kw4">SEL</span> failedAction;<br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">id</span><span class="br0">&#41;</span>initWithDelegate<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">id</span><span class="br0">&#41;</span>delegate selSucceeded<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">SEL</span><span class="br0">&#41;</span>succeeded selFailed<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">SEL</span><span class="br0">&#41;</span>failed;<br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">BOOL</span><span class="br0">&#41;</span>startRequestForURL<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span class="kw5">NSURL</span></a><span class="sy0">*</span><span class="br0">&#41;</span>url;<br />
<span class="kw1">@end</span></div></div><br />
In this sample class receivedData is where the response will be stored, the connectionDelegate refers to what will be the target of the succeededAction and failedAction messages. After all, that&#8217;s all I really care about when making this request: success or failure notification. Now your connection controller can be instantiated like this:</p>
<p><div id="wpshdo_2" class="wp-synhighlighter-outer"><div id="wpshdt_2" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_2"></a><a id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">Calling code example usage</a></td><td align="right"><a href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_2" class="wp-synhighlighter-inner" style="display: block;"><span class="kw4">id</span> delegate <span class="sy0">=</span> self;<br />
myConnectionController<span class="sy0">*</span> connectionController <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span><span class="br0">&#91;</span>myConnectionController alloc<span class="br0">&#93;</span> initWithDelegate<span class="sy0">:</span>delegate<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;selSucceeded<span class="sy0">:</span><span class="kw1">@selector</span><span class="br0">&#40;</span>connectionSucceeded<span class="sy0">:</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selFailed<span class="sy0">:</span><span class="kw1">@selector</span><span class="br0">&#40;</span>connectionFailed<span class="sy0">:</span><span class="br0">&#41;</span><span class="br0">&#93;</span> autorelease<span class="br0">&#93;</span>;<br />
<span class="br0">&#91;</span>myConnectionController startRequestForURL<span class="sy0">:</span><span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span class="kw5">NSURL</span></a> URLWithString<span class="sy0">:</span><span class="co3">@</span><span class="st0">&quot;http://request.org/somequery.php&quot;</span><span class="br0">&#93;</span><span class="br0">&#93;</span>;</div></div><br />
You also need to implement the callbacks. These will take the response data and parse it, typically, or handle any error conditions. Although the request is handled asynchronously by the URL Loading System, your callbacks are signalled on the main thread, and you may not want to tie it up parsing large chunks of XML or JSON. Next time I&#8217;ll write about using NSOperationQueue to do the parsing in a background thread so the UI remains responsive.<br />
<div id="wpshdo_3" class="wp-synhighlighter-outer"><div id="wpshdt_3" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_3"></a><a id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">Callback methods</a></td><td align="right"><a href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_3" class="wp-synhighlighter-inner" style="display: block;"><span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connectionSucceeded<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableData_Class/"><span class="kw5">NSMutableData</span></a><span class="sy0">*</span><span class="br0">&#41;</span>data <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co2">// data contains response, e.g. JSON to be parsed</span><br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connectionFailed<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a><span class="sy0">*</span><span class="br0">&#41;</span>error <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co2">// error contains reason for failure</span><br />
<span class="br0">&#125;</span></div></div><br />
This is a totally trivial example, but you can see how easy it will be to a) define multiple callback handlers for any given class, and thus allowing for multiple NSURLConnections, and b) subclass myConnectionController for specialized request handling. This is what the default implementation looks like:<br />
<div id="wpshdo_4" class="wp-synhighlighter-outer"><div id="wpshdt_4" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_4"></a><a id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">myConnectionController implementation</a></td><td align="right"><a href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_4" class="wp-synhighlighter-inner" style="display: block;"><span class="kw1">@implementation</span> myConnectionController<br />
<span class="kw1">@synthesize</span> connectionDelegate;<br />
<span class="kw1">@synthesize</span> succeededAction;<br />
<span class="kw1">@synthesize</span> failedAction;<br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">id</span><span class="br0">&#41;</span>initWithDelegate<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">id</span><span class="br0">&#41;</span>delegate selSucceeded<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">SEL</span><span class="br0">&#41;</span>succeeded selFailed<span class="sy0">:</span><span class="br0">&#40;</span><span class="kw4">SEL</span><span class="br0">&#41;</span>failed <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>self <span class="sy0">=</span> <span class="br0">&#91;</span>super init<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; self.connectionDelegate <span class="sy0">=</span> delegate;<br />
&nbsp; &nbsp; &nbsp; &nbsp; self.succeededAction <span class="sy0">=</span> succeeded;<br />
&nbsp; &nbsp; &nbsp; &nbsp; self.failedAction <span class="sy0">=</span> failed;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> self;<br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>dealloc <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>connectionDelegate release<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>super dealloc<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">BOOL</span><span class="br0">&#41;</span>startRequestForURL<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span class="kw5">NSURL</span></a><span class="sy0">*</span><span class="br0">&#41;</span>url <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableURLRequest_Class/"><span class="kw5">NSMutableURLRequest</span></a><span class="sy0">*</span> urlRequest <span class="sy0">=</span> <span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableURLRequest_Class/"><span class="kw5">NSMutableURLRequest</span></a> requestWithURL<span class="sy0">:</span>url<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="co2">// cache &amp; policy stuff here</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span><span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/"><span class="kw5">NSURLCache</span></a> sharedURLCache<span class="br0">&#93;</span> removeAllCachedResponses<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>urlRequest setHTTPMethod<span class="sy0">:</span><span class="co3">@</span><span class="st0">&quot;POST&quot;</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>urlRequest setHTTPShouldHandleCookies<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a><span class="sy0">*</span> connectionResponse <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span><span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a> alloc<span class="br0">&#93;</span> initWithRequest<span class="sy0">:</span>urlRequest delegate<span class="sy0">:</span>self<span class="br0">&#93;</span> autorelease<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>connectionResponse<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co2">// handle error</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NO</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; receivedData <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableData_Class/"><span class="kw5">NSMutableData</span></a> data<span class="br0">&#93;</span> retain<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">YES</span>;<br />
<span class="br0">&#125;</span></div></div></p>
<p>And finally, the standard delegate methods for NSURLConnection are hidden inside the myConnectionController implementation. These should be familiar if you&#8217;ve ever used NSURLConnection directly:</p>
<p><div id="wpshdo_5" class="wp-synhighlighter-outer"><div id="wpshdt_5" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_5"></a><a id="wpshat_5" class="wp-synhighlighter-title" href="#codesyntax_5"  onClick="javascript:wpsh_toggleBlock(5)" title="Click to show/hide code block">NSURLConnectionDelegate methods</a></td><td align="right"><a href="#codesyntax_5" onClick="javascript:wpsh_code(5)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_5" onClick="javascript:wpsh_print(5)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mundue.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_5" class="wp-synhighlighter-inner" style="display: block;"><span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connection<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a><span class="sy0">*</span><span class="br0">&#41;</span>connection didReceiveResponse<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLResponse_Class/"><span class="kw5">NSURLResponse</span></a><span class="sy0">*</span><span class="br0">&#41;</span>response <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>receivedData setLength<span class="sy0">:</span>0<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connection<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a><span class="sy0">*</span><span class="br0">&#41;</span>connection didReceiveData<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span class="kw5">NSData</span></a><span class="sy0">*</span><span class="br0">&#41;</span>data <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>receivedData appendData<span class="sy0">:</span>data<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connection<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a><span class="sy0">*</span><span class="br0">&#41;</span>connection didFailWithError<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a><span class="sy0">*</span><span class="br0">&#41;</span>error <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>connectionDelegate performSelector<span class="sy0">:</span>failedAction withObject<span class="sy0">:</span>error<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>receivedData release<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>connectionDidFinishLoading<span class="sy0">:</span><span class="br0">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/"><span class="kw5">NSURLConnection</span></a><span class="sy0">*</span><span class="br0">&#41;</span>connection <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>connectionDelegate performSelector<span class="sy0">:</span>succeededAction withObject<span class="sy0">:</span>receivedData<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>receivedData release<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="kw1">@end</span></div></div><br />
That should be enough to get you started. Hopefully you won&#8217;t find it too hard to extend this to add the ability to cancel a request, etc.</p>
<hr/>
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>,</em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/07/simple-http-request-handling/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>3 Years On The App Store</title>
		<link>http://blog.mundue.net/2011/07/3-years-on-the-app-store/</link>
		<comments>http://blog.mundue.net/2011/07/3-years-on-the-app-store/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 23:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[App Store]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=432</guid>
		<description><![CDATA[This week marks the 3rd anniversary of the App Store launch. It sounds, and feels like a lifetime ago. It&#8217;s sometimes hard to remember how &#8220;unconnected&#8221; our lives were before the iPhone, but I can say that prior to June of 2007 I absolutely hated every cell phone I owned. There was the Qualcomm clunker, [...]]]></description>
				<content:encoded><![CDATA[<p>This week marks the 3rd anniversary of the App Store launch. It sounds, and feels like a lifetime ago. It&#8217;s sometimes hard to remember how &#8220;unconnected&#8221; our lives were before the iPhone, but I can say that prior to June of 2007 I absolutely hated every cell phone I owned. There was the Qualcomm clunker, the Motorola junker, the Samsung clamshell, etc. More often than not the phone was merely a device to slap the carrier&#8217;s label on to. People got a &#8220;verizon phone,&#8221; or an &#8220;at&amp;t phone&#8221; if you lived in the U.S. We were, and still are, captives of the telcos, but that&#8217;s starting to change finally.</p>
<p><span id="more-432"></span>
<p>When the App Store opened, I dreamed of working for myself. After 26 years of service in academia and Corporate America I was tiring of enormous org charts and meaningless schedules. It took a little bit of time, but in late 2009 I finally quit my last day job. By then we had built up a little stable of apps, and the income was starting to pick up. I&#8217;ll never regret that decision, as many indie developers will tell you: once you work for yourself you&#8217;ll never want to go back to working for &#8216;the man&#8217;.</p>
<p>Year three on the App Store was an exciting one for us. Mundue apps have now been downloaded a total of 9.2 million times, about 95% of which are free apps. We released two new iOS apps this past year, and are working on a few more at the moment, and also created Mac and Android versions of reMovem. I gave a talk on ad network mediation at the Austin 360iDev conference, and met many new friends there and at other conferences. If you have the opportunity to attend the next 360iDev, this September in <a href="http://360idev.com/">Denver</a>, I highly recommend that you do so.</p>
<p>So what will year four be like? I&#8217;m very optimistic about the upcoming changes in iOS 5. With the sales of iOS devices still very strong, it looks like the next year or two will be even better for app developers. With over 400,000 apps in the store, the bad news is that your piece of the pie is constantly shrinking, but the good news is that the pie keeps growing ever larger with no slowdown in sight.</p>
<hr />
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>,</em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/07/3-years-on-the-app-store/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>In With the New</title>
		<link>http://blog.mundue.net/2011/06/in-with-the-new/</link>
		<comments>http://blog.mundue.net/2011/06/in-with-the-new/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 18:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Xcode]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=427</guid>
		<description><![CDATA[The new shiny is here. At the annual WWDC recently, Apple unveiled three widely-anticipated new products. This year it was all about software, so hardware announcements will have to come later. In the keynote Steve Jobs mentioned OS X Lion, iOS 5, and iCloud. If you&#8217;re an iOS or Mac developer these changes will have [...]]]></description>
				<content:encoded><![CDATA[<p>The new shiny is here. At the annual WWDC recently, Apple unveiled three widely-anticipated new products. This year it was all about software, so hardware announcements will have to come later. In the keynote Steve Jobs mentioned OS X Lion, iOS 5, and iCloud. If you&#8217;re an iOS or Mac developer these changes will have a huge impact on you in the next few months. I&#8217;m not going to go into much detail about the announcements, but you should definitely check out the <a href="http://www.apple.com/apple-events/wwdc-2011/">keynote</a> if you haven&#8217;t seen it yet.</p>
<p><span id="more-427"></span></p>
<p>The changes in <a href="http://www.apple.com/macosx/">Lion</a> are impressive; I consider it the most significant update since OS X was first released 10 years ago. Developers will want to rev their desktop apps to take advantage of the many new features, like Autosave, Resume, Versions, and Fullscreen. Some of the features we&#8217;ve long had on iOS are coming to the desktop in a big way, and this really does fulfill the &#8220;Back to the Mac&#8221; promise. If you don&#8217;t have a trackpad yet, you&#8217;ll want one for Lion. Lion&#8217;s on the immediate horizon with a scheduled July release.</p>
<p>Similar in scope is the <a href="http://www.apple.com/ios/ios5/">iOS 5</a> update. Even if you don&#8217;t appreciate each of the 200 listed new features, you are going to be impressed with the new Notification Center, Reminders, and, hold the applause, wireless syncing. Billed as <strong><em>PC Free</em></strong>, Apple doesn&#8217;t even call this syncing, but it&#8217;s supposed to allow for wireless activation, backup, and updating. Although they&#8217;ve had some of this functionality on Android for a while, Apple&#8217;s superior user experience really shines here.</p>
<p style="text-align: left;">The game-changer of the three is of course <a href="http://www.apple.com/icloud/">iCloud</a>, long speculated as Apple&#8217;s sync service “in the cloud.” But it&#8217;s much much more than that. By seamlessly storing data in a central wireless repository and automatically syncing it to all your devices (desktop &amp; mobile), the problem of syncing multiple devices should be eliminated. Like many, I&#8217;ve suffered though the pain of MobileMe duplicating and removing contacts, calendar entries, and email settings. With six iOS devices and three Macs sitting in front of me right now, this solution can&#8217;t come soon enough. I expect some new breeds of apps designed to take collaboration (with self &amp; others) to the next level. In addition, even for casual games like reMovem it will be easy to save game state so you can start it on your iPod touch and finish the <em>same game</em> later on your iPad.</p>
<p>If iCloud is the glue that holds apps together, then <a href="http://developer.apple.com/xcode/">Xcode 4</a> is the all-in-one tool needed to build them. In order to work with any of the newer SDKs you should already be using a version of Xcode 4. I hesitated for quite some time, mostly because my experience with the early pre-release versions was less than satisfactory. Around the time of the VTM Seattle conference (early April) I made a conscious effort to switch from Xcode 3.2.6 to Xcode 4. Honestly I haven&#8217;t regretted it one bit. I know there are some things that don&#8217;t work right, but luckily I&#8217;m not using the Core Data modeling which is broken. If you do, then I can understand the hesitation.</p>
<p>I&#8217;ve been using Xcode 4 exclusively now for 3 months and it&#8217;s really a nice improvement in many ways over the previous versions. I&#8217;ve used it for a couple of client projects and submitted three of my own apps with it during that time. Once you get over the learning curve, and it is steep, you&#8217;ll be happy you made the switch. We&#8217;re often asked by new developers, &#8220;Where do I start?” Although all of the beginning iPhone development books reference Xcode 3, you&#8217;d be better suited to dive into Xcode 4 right away and avoid any uncomfortable transition.</p>
<p>After seeing some of the presentations at WWDC when the Apple folks made Xcode do the almost-unthinkable, it&#8217;s clear that its capabilities (now, and planned for the near future) were carefully thought out. Yes it&#8217;s a beast, but one you can customize to fit your workflow if that&#8217;s your preference. If you&#8217;re still on the fence about Xcode 4, I recommend you give it a try soon so you can get on with the new shiny bits. Lion is nearly upon us, and iOS 5 awaits your exploration!</p>
<hr style="font-family: 'Lucida Grande';" />
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>,</em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/06/in-with-the-new/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Annual Pilgrimage</title>
		<link>http://blog.mundue.net/2011/06/annual-pilgrimage/</link>
		<comments>http://blog.mundue.net/2011/06/annual-pilgrimage/#comments</comments>
		<pubDate>Mon, 06 Jun 2011 12:00:36 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=424</guid>
		<description><![CDATA[The annual pilgrimage to San Francisco is underway this week. I figure I&#8217;ve attended about a dozen in the past 21 years. All have indeed been awesome. Many long-time attendees seem to have mastered the week-long partying and a few have even published &#8220;survival guides.&#8221; My goal is not to get as many free drinks [...]]]></description>
				<content:encoded><![CDATA[<p><img style="float: left;" title="WWDC2011.png" src="http://blog.mundue.net/wp-content/uploads/2011/06/appstoreWWDC2011.png" border="0" alt="WWDC 2011" hspace="10" width="63" height="79" />The annual pilgrimage to San Francisco is underway this week. I figure I&#8217;ve attended about a dozen in the past 21 years. All have indeed been awesome. Many long-time attendees seem to have mastered the week-long partying and a few have even published &#8220;survival guides.&#8221; My goal is not to get as many free drinks as I can, or to stay awake during the late-afternoon sessions. I&#8217;m here to see old friends, make new ones, and absorb the latest installment of greatness from Apple. I came prepared with questions, code problems, and and open mind about what&#8217;s next for iOS and OS X. Seeing a live Stevenote will be a bonus.</p>
<p><span id="more-424"></span></p>
<p>Yes the conference has grown a great deal since the 1990&#8242;s in San Jose. I think there were barely 1,000 attendees that year. But it&#8217;s still easy to find people in the crowds or in the streets around the conference center. Most will have iPhones or iPads and Twitter at the ready, and the proliferation of third-party events means you&#8217;ll likely run into someone more than once without even trying.</p>
<p>There are an awful lot of <a href="https://developer.apple.com/wwdc/schedule/">To Be Announced</a> sessions at the time I am writing this. I&#8217;m not sure what to make of it except that we&#8217;re sure to see a few surprises this morning. No, we won&#8217;t be getting free iPhones, but around noontime today I guarantee we&#8217;ll all be maneuvering to plug in ethernet cables and download the pre-release of [REDACTED].</p>
<p>If you&#8217;re not here I&#8217;m sure you&#8217;re watching a live stream of the day&#8217;s events. Hang in there, all will soon be revealed. If you are here and you see me, please say hi!</p>
<hr style="font-family: 'Lucida Grande';" />
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>, </em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/06/annual-pilgrimage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Care and Feeding of Your Search Paths</title>
		<link>http://blog.mundue.net/2011/05/library-search-paths/</link>
		<comments>http://blog.mundue.net/2011/05/library-search-paths/#comments</comments>
		<pubDate>Mon, 23 May 2011 12:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Xcode]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=399</guid>
		<description><![CDATA[I ran into an odd issue the other day and spent a little time getting to the bottom of it. It turns out I wasn&#8217;t taking good care of my Xcode project&#8217;s library search paths. Here&#8217;s what I had to do about it and why you might care. Note this problem has likely been lurking [...]]]></description>
				<content:encoded><![CDATA[<p>I ran into an odd issue the other day and spent a little time getting to the bottom of it. It turns out I wasn&#8217;t taking good care of my Xcode project&#8217;s library search paths. Here&#8217;s what I had to do about it and why you might care. Note this problem has likely been lurking in my project for some months, and may have caused other unintended consequences.</p>
<p><span id="more-399"></span><br />
<span style="font-size: 15px; font-weight: bold;">The Symptom</span></p>
<p>I was in the middle of updating a project with the latest AdWhirl and Millennial Media SDKs. If you are not familiar, the AdWhirl SDK uses the Millennial Media SDK and both have been changed recently to use a newer method in the MMAdView class. This ended up causing a runtime error, followed by a helpful stacktrace:</p>
<pre>2011-05-10 17:11:43.105 reMovemFree[1630:707] +[MMAdView adWithFrame:type:apid:delegate:loadAd:startTimer:]: unrecognized selector sent to class 0x118c48</pre>
<pre>2011-05-10 17:11:43.184 reMovemFree[1630:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[MMAdView adWithFrame:type:apid:delegate:loadAd:startTimer:]: unrecognized selector sent to class 0x118c48'</pre>
<p>I puzzled over this for a few hours trying to figure out just why this happened. The headers files were correct, and obviously the project was linking without a problem. At this point I didn&#8217;t want to write any more debugging or introspection code, but I was really just looking for a way to find out exactly which methods the class did support. That turned out to be a dead-end anyway.†</p>
<h3>The Cause</h3>
<p>If you work with 3rd-party SDKs you might be accustomed to taking updates every few months or so. After some time you have probably updated certain libraries many times. I know I do this quite often. Many of you are probably way ahead of me here and can see where this is going. When you (literally) drop in a new SDK, and delete the old one, Xcode adds the new SDK path to the Library Search Paths for the project. Which is fine:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="drop-in-sdks.jpeg" src="http://blog.mundue.net/wp-content/uploads/2011/05/appstoredrop-in-sdks.jpeg" border="0" alt="Drop in sdks" width="600" height="152" /></p>
<p>The problem is that Xcode didn&#8217;t delete the old SDK from the search paths when I dragged it out of the project. Since the build links with the <em>first</em> version of a library it finds on the search paths, any older version will usually do. Here&#8217;s what happens after repeatedly dropping in new versions of SDKs:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="multiple-sdks.jpeg" src="http://blog.mundue.net/wp-content/uploads/2011/05/appstoremultiple-sdks.jpeg" border="0" alt="Multiple sdks" width="600" height="152" /></p>
<p>So what really happened was that I was linking to the earlier version 4.1.0 of the Millennial Media SDK, not the latest 4.2.4, even though both were on the library search path. This seems like a deficiency in Xcode, since it appears to go to lengths to track external referenced file dependencies.</p>
<h3>The Solution</h3>
<p>The simple solution for me was to go in and manually prune the old SDK paths from the Library Search Path setting for my project. And of course, add a note in my &#8220;todo&#8221; list for future updates to take care when adding new SDKs. Unfortunately the Xcode 4 widget for editing the Library Search Path setting is a little funky compared to the Xcode 3 version. I managed to get it shrunk down so small it is barely usable, but with a great deal of patience I was able to find and zap the offending entries.</p>
<p>Incidentally, you may want to take advantage of Xcode&#8217;s Source Trees preference, which lets you define an external folder, give it a symbolic name, and refer to in inside your project. This is super handy for two reasons, 1) it dramatically shortens all the nearly-unreadable $(SDKROOT)/../../../etc paths, and 2) it makes code portability to different machines with different folder structures much easier. It turns this:</p>
<hr />
<p><img class="aligncenter" style="display: block; margin-left: auto; margin-right: auto; border: 0px initial initial;" title="ugly-paths.jpeg" src="http://blog.mundue.net/wp-content/uploads/2011/05/appstoreugly-paths1.jpeg" border="0" alt="Ugly paths" width="258" height="151" /></p>
<hr />
<p>into this:</p>
<hr />
<p><img class="aligncenter" style="display: block; margin-left: auto; margin-right: auto; border: 0px initial initial;" title="better-paths.jpeg" src="http://blog.mundue.net/wp-content/uploads/2011/05/appstorebetter-paths1.jpeg" border="0" alt="Better paths" width="258" height="151" /></p>
<hr />
<p>Hope this helps a little, even if just to remind you to double-check those Library Search Path settings next time you drop in a new replacement library from a 3rd-party vendor. If you know of a better way to manage this issue, I&#8217;d love to hear about it.</p>
<p>† The commandline tool &#8220;otool&#8221; is great for examining dynamic and static libraries. The problem for me was that I examined the libraries I assumed were linking, not the ones that were actually linking. Looking at the wrong library didn&#8217;t help, since it obviously had the right method signatures:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="otool-output.jpeg" src="http://blog.mundue.net/wp-content/uploads/2011/05/appstoreotool-output.jpeg" border="0" alt="Otool output" width="511" height="291" /></p>
<hr />
<p style="font-family: 'Lucida Grande';"><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>, </em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/05/library-search-paths/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prompting for Reviews</title>
		<link>http://blog.mundue.net/2011/05/prompting-for-reviews/</link>
		<comments>http://blog.mundue.net/2011/05/prompting-for-reviews/#comments</comments>
		<pubDate>Mon, 09 May 2011 16:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[App Store]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iDevBlogADay]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=362</guid>
		<description><![CDATA[Like pay-to-play or in-app ads, prompting for a rating is controversial in that some developers frown upon it. Free apps tend to have an average 3 star rating. People rarely bother to go back to the App Store to rate an app. There&#8217;s always a small minority that will go out of their way to [...]]]></description>
				<content:encoded><![CDATA[<p>Like pay-to-play or in-app ads, prompting for a rating is controversial in that some developers frown upon it. Free apps tend to have an average 3 star rating.  People rarely bother to go back to the App Store to rate an app. There&#8217;s always a small minority that will go out of their way to provide negative reviews. So why not solicit positive feedback by providing a reminder to rate the game? In my opinion, there&#8217;s nothing overtly annoying or obnoxious about presenting an alert view that can easily be dismissed.</p>
<p><span id="more-362"></span></p>
<p>I rolled my own code to prompt users for a review and the results have been excellent. We&#8217;re now getting mostly 4 and 5 star ratings in the prompt-enabled apps. The key of course is in the timing of the prompts. I&#8217;ll explain a little about how the code works, then discuss the results so far. For a far better complete code template and explanation see also Noel Llopis&#8217;s <a href="http://gamesfromwithin.com/increase-your-app-ratings-on-the-app-store">blog post</a> from last year.</p>
<p>Since the stated objective is to get positive feedback without annoying the user, we want to filter out people who have just launched the app for the first time. One way to do this would be to use a timer, maybe wait until some period of time has elapsed. That&#8217;s probably OK, but could lead to a prompt coming up at a truly random time. Instead I have code that checks for two things: time elapsed plus a new high score achieved. To detect a desired length of time, use something like this in your -[UIApplicationDelegate application:didFinishLaunchingWithOptions:] method:</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #033efc;">if</span> (![defaults <span style="color: #3b95ae;">objectForKey</span>:<span style="color: #033efc;">kFirstRunKey</span>]) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;">    [defaults </span>setObject<span style="color: #000000;">:[</span>NSDate<span style="color: #000000;"> </span>date<span style="color: #000000;">] </span>forKey<span style="color: #000000;">:</span><span style="color: #033efc;">kFirstRunKey</span><span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;">}</span></pre>
<p>This gives you the timestamp of the first run time. I typically define kFirstRunKey to include a unique version number, so I can record the first run of each update. Now each time a new high score (use whatever criteria you see fit) is achieved, check the current time against the first run timestamp, like this:</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #033efc;">void</span>) askToRateApp {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;"> </span><span style="color: #033efc;">if</span> ( ![<span style="color: #033efc;">self</span> <span style="color: #3b95ae;">reachable</span>] )</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;">   </span></span>return<span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span>NSUserDefaults<span style="color: #000000;">* defaults = [</span>NSUserDefaults<span style="color: #000000;"> </span>standardUserDefaults<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span>if<span style="color: #000000;"> ( [defaults </span><span style="color: #3b95ae;">boolForKey</span><span style="color: #000000;">:</span>kAlreadyDeclinedToRateKey<span style="color: #000000;">] )</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;">   </span></span>return<span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span>NSTimeInterval<span style="color: #000000;"> elapsed = [[</span>NSDate<span style="color: #000000;"> </span>date<span style="color: #000000;">] </span>timeIntervalSinceDate<span style="color: #000000;">:[defaults </span>objectForKey<span style="color: #000000;">:</span><span style="color: #033efc;">kFirstRunKey</span><span style="color: #000000;">]];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span><span style="color: #033efc;">if</span><span style="color: #000000;"> (elapsed &lt; </span><span style="color: #033efc;">kAskDelaySeconds</span><span style="color: #000000;"> )<span style="white-space: pre;"> </span></span>// approximately 1 day</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;">   </span></span>return<span style="color: #000000;">;</span></pre>
<p>Notice a couple of interesting things here. First, I have a Reachability test to exit early if there&#8217;s no connection. Second, if the user has previously declined to rate the app, respect that choice and do nothing. Finally, there is a test to see if enough time has elapsed. If not, again do nothing. At this point you could prompt the user, or optionally add more tests. Maybe you only want to prompt on the 17th high score. Then something like this would work:</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;"> </span><span style="color: #3b95ae;">NSInteger</span> showAsk = [defaults <span style="color: #3b95ae;">integerForKey</span>:<span style="color: #033efc;">kShowAskToRateKey</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span>// If showAsk is 0, the prompt screen will be shown.</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;"> </span></span>// If showAsk is &gt; 0, we decrement it now.</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;"> </span><span style="color: #033efc;">if</span> ( showAsk == 0 ) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;">   </span></span>feedbackAlert<span style="color: #000000;"> = [[[</span>UIAlertView<span style="color: #000000;"> </span>alloc<span style="color: #000000;">] </span>initWithTitle<span style="color: #000000;">:</span><span style="color: #033efc;">NSLocalizedString</span><span style="color: #000000;">(</span><span style="color: #b12620;">@"AskToRateApp"</span><span style="color: #000000;">,</span><span style="color: #b12620;">@""</span><span style="color: #000000;">) </span>message<span style="color: #000000;">:</span><span style="color: #033efc;">nil </span><span style="color: #000000;"><span style="color: #3b95ae;">delegate</span>:<span style="color: #033efc;">self </span></span><span style="color: #000000;"><span style="color: #3b95ae;">cancelButtonTitle</span>:<span style="color: #033efc;">NSLocalizedString</span>(<span style="color: #b12620;">@"NoThanks"</span>,<span style="color: #b12620;">@""</span>) <span style="color: #033efc;"><span style="color: #3b95ae;">otherButtonTitles</span><span style="color: #000000;">:</span>NSLocalizedString<span style="color: #000000;">(</span><span style="color: #b12620;">@"RateNow"</span><span style="color: #000000;">,</span><span style="color: #b12620;">@""</span><span style="color: #000000;">), </span>NSLocalizedString<span style="color: #000000;">(</span><span style="color: #b12620;">@"RemindLater"</span><span style="color: #000000;">,</span><span style="color: #b12620;">@""</span><span style="color: #000000;">), </span>nil<span style="color: #000000;">] </span></span><span style="color: #3b95ae;">autorelease<span style="color: #000000;">];</span></span></span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;">   </span>[</span>feedbackAlert<span style="color: #000000;"> </span>show<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;"> </span>} <span style="color: #033efc;">else</span> {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;">   </span>showAsk = (showAsk - 1) ;</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;">   </span>[defaults <span style="color: #3b95ae;">setInteger</span>:showAsk <span style="color: #3b95ae;">forKey</span>:<span style="color: #033efc;">kShowAskToRateKey</span>];</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;"> </span>}</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</pre>
<p>In this example, the showAsk variable is tested to see if the counter is zero. If it is, we show the feedback alert. Otherwise we decrement it and store it back in the default settings for next time. Set a reasonable initial value for kShowAskToRateKey. Once the saved value reaches zero, the alert will be shown exactly once. All that&#8217;s left to do is handle the buttons on the feedback alert.</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #033efc;">void</span>)alertView:(<span style="color: #3b95ae;">UIAlertView</span> *)alertView clickedButtonAtIndex:(<span style="color: #3b95ae;">NSInteger</span>)buttonIndex</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">{</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">  <span style="color: #033efc;">if</span> ( alertView == <span style="color: #3b95ae;">feedbackAlert</span> ) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;">    </span>NSUserDefaults<span style="color: #000000;">* defaults = [</span>NSUserDefaults<span style="color: #000000;"> </span>standardUserDefaults<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;">    </span><span style="color: #033efc;">if</span> ( buttonIndex == 0 ) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;">      </span></span>// No Thanks</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;">      </span><span style="color: #0c8e12;">// Don't Ask Anymore</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;">      </span>[defaults </span><span style="color: #3b95ae;">setBool</span><span style="color: #000000;">:</span>YES<span style="color: #000000;"> </span><span style="color: #3b95ae;">forKey</span><span style="color: #000000;">:</span>kAlreadyDeclinedToRateKey<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">    } <span style="color: #033efc;">else</span> <span style="color: #033efc;">if</span> ( buttonIndex == 1 ){</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;">      </span></span>// Rate Now...</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;">      </span></span>// and Don't Ask Anymore</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #033efc;"><span style="color: #000000;"><span style="white-space: pre;">      </span>[defaults </span><span style="color: #3b95ae;">setBool</span><span style="color: #000000;">:</span>YES<span style="color: #000000;"> </span><span style="color: #3b95ae;">forKey</span><span style="color: #000000;">:</span>kAlreadyDeclinedToRateKey<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;">      </span>[</span>self<span style="color: #000000;"> </span>showAppStoreReviewPage<span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><span style="white-space: pre;">    </span>} <span style="color: #033efc;">else</span> <span style="color: #033efc;">if</span> ( buttonIndex == 2 ) {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #0c8e12;"><span style="color: #000000;"><span style="white-space: pre;">      </span></span>// Remind Me Later</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;">      </span>[defaults <span style="color: #3b95ae;">setInteger</span>:21 <span style="color: #3b95ae;">forKey</span>:<span style="color: #033efc;">kShowAskToRateKey</span>];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;">    </span>}</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3b95ae;"><span style="color: #000000;"><span style="white-space: pre;">    </span></span>feedbackAlert<span style="color: #000000;"> = </span><span style="color: #033efc;">nil</span><span style="color: #000000;">;</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;">  </span>}</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</pre>
<p>For the &#8220;remind later&#8221; choice here, I&#8217;m resetting the kShowAskToRateKey to 21, but this can be any value you like. I recommend you use analytics or some other method to determine an appropriate measure of how much time is &#8220;later.&#8221; FInally you need a small piece of code to make the App Store review page show. This technique can be used on iPhone, iPod touch, iPad, and Mac, but on iPad and Mac it is not possible to go directly to the review page. You&#8217;ll go instead to the App description and may want to explain how to actually enter a rating or review in those cases.</p>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #033efc;">void</span>) showAppStoreReviewPage {</pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="color: #000000;">  [[</span>UIApplication<span style="color: #000000;"> </span>sharedApplication<span style="color: #000000;">] </span>openURL<span style="color: #000000;">:</span><span style="color: #000000;">[</span>NSURL<span style="color: #000000;"> </span>URLWithString<span style="color: #000000;">:</span>deepLinkReview<span style="color: #000000;">]</span><span style="color: #000000;">];</span></pre>
<pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</pre>
<p>For the deepLinkReview you will specify the URL that takes users to the application&#8217;s review page on iTunes. It&#8217;s pretty straightforward to construct the URL manually. Justine Pratt wrote all about this on <a href="http://creativealgorithms.com/blog/content/review-app-links-sorted-out">her blog</a> last year. You can also wrap the URL in a LinkShare link if you are an iTunes affiliate.</p>
<p>So how well does it work? Like Noel I have see an improvement in reMovem ratings from 3.5 stars to 4.5 stars, with about twice as many written reviews per day as there were a year ago. Still, 2 out of 3 users choose not to leave reviews. Of the rest, half opt for the &#8220;remind later&#8221; choice while about 15% click the &#8220;rate now&#8221; button. I suspect only a percentage of those actually complete the process, but it&#8217;s better than none. It&#8217;s debatable whether this leads to more sales, but having more 4 and 5 star reviews certainly helps when people are looking at the App Store description. I also believe they use the number of reviews as a gauge to an app&#8217;s popularity, and, in turn, as a data point for their purchasing decision. So the more reviews, the better.</p>
<p><img src="http://blog.mundue.net/wp-content/uploads/2011/05/appstoreNewImage.png" border="0" alt="NewImage" width="100%" /></p>
<p>&#8212;-</p>
<p><em>This post is part of </em><a href="http://idevblogaday.com/"><em>iDevBlogADay</em></a><em>, a group of indie iOS development blogs featuring two new posts per day. You can keep up with iDevBlogADay through the </em><a href="http://idevblogaday.com/"><em>web site</em></a><em>, </em><a href="http://feeds.feedburner.com/idevblogaday"><em>RSS feed</em></a><em>, or </em><a href="http://twitter.com/#search?q=%23idevblogaday"><em>Twitter</em></a><em>.</em></p>
<div><em><br />
</em></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/05/prompting-for-reviews/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>One of the Good Guys</title>
		<link>http://blog.mundue.net/2011/04/agon-shutting-down/</link>
		<comments>http://blog.mundue.net/2011/04/agon-shutting-down/#comments</comments>
		<pubDate>Sun, 03 Apr 2011 01:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[App Store]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=359</guid>
		<description><![CDATA[We are sad to see that AGON Online is shutting down at the end of June. A couple of years ago when I was researching services for online leaderboards, I decided to use AGON for two of our holiday games. This was an easy choice on my part, because at the time Open Feint and [...]]]></description>
				<content:encoded><![CDATA[<p>We are sad to see that AGON Online is <a href="http://developer.agon-online.com/2011/03/31/agon-online-shutting-down/">shutting down</a> at the end of June. A couple of years ago when I was researching services for online leaderboards, I decided to use AGON for two of our holiday games. This was an easy choice on my part, because at the time Open Feint and Scoreloop were a little rough around the edges. Both have matured fantastically, of course, and with the advent of Game Center, the folks at Aptocore (makers of AGON Online) have felt the inevitable squeeze of the bigger competitors.</p>
<p><span id="more-359"></span>
<p>Nevertheless, from the very beginning it was a pleasure to deal with the folks at Aptocore. The system they built was easy to integrate and manage, and the SDK had an excellent Xcode-integrated documentation set. The support team was knowledgeable and courteous, and always very professional. We&#8217;ll miss working  with them, and wish them well in their future endeavors.</p>
<p>Many developers used AGON in some interesting games. A few of my favorites were: <a href="http://www.agon-online.com/game/B5BC216D4623B58FA1CBF91210C34675B2C132B8">Eyegore&#8217;s Eye Blast</a>, <a href="http://www.agon-online.com/game/C7DA2CB7EC4945D321DD91916BF08F6F62EC4AD0">Similis Deluxe</a>, <a href="http://www.agon-online.com/game/40AFF2509A0E39C2F070C5D20551252AC1274549">Sheepstacker</a>, <a href="http://www.agon-online.com/game/436F0B32FA219FA0090B247F00A879CFE34523A2">Popper</a>, <a href="http://www.agon-online.com/game/FF234B8CB1B660EA5F92D84465124EAE45138F1F">Inkvaders</a>, <a href="http://www.agon-online.com/game/8EAAE9D3CBAC135D810710BF8D55AE3E9939ACF8">SpringFling</a>, and <a href="http://www.agon-online.com/game/D51420932D9FEE5D052A2BCDA9BC2BC49E22A009">Azplode</a>. Check &#8216;em out!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/04/agon-shutting-down/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VTM iPhone Seattle</title>
		<link>http://blog.mundue.net/2011/03/vtm-seattle-2011/</link>
		<comments>http://blog.mundue.net/2011/03/vtm-seattle-2011/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 20:00:00 +0000</pubDate>
		<dc:creator>mundue</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.mundue.net/?p=352</guid>
		<description><![CDATA[Soon we&#8217;ll be heading to Seattle for the biannual VTM iPhone conference. This two day event will be held the weekend April 9-10, with an optional third day of seminars the day before. This will be my third Voices That Matter conference, and I&#8217;m looking forward to some great sessions and seeing old friends again. [...]]]></description>
				<content:encoded><![CDATA[<p><img style="float: left;" title="vtm_iphone.png" src="http://blog.mundue.net/wp-content/uploads/2011/03/appstorevtm_iphone.png" border="0" alt="NewImage" hspace="10" width="114" height="80" /></p>
<p>Soon we&#8217;ll be heading to Seattle for the biannual <a href="http://iphonespring2011.crowdvine.com/">VTM iPhone</a> conference. This two day event will be held the weekend April 9-10, with an optional third day of seminars the day before. This will be my third Voices That Matter conference, and I&#8217;m looking forward to some great sessions and seeing old friends again. I&#8217;m also very interested in the hands-on cocos2d seminar with Rod Strougo and Ray Wenderlich on Friday. For those new to Cocoa and Objective-C there&#8217;s also a full-day session with the Big Nerd Ranch guys Aaron Hillegass and Joe Conway.</p>
<p><span id="more-352"></span></p>
<p>Most of the presenters at VTM are authors and experts on iOS development, which leads to the motto of &#8220;learn from those who wrote the book.&#8221; There&#8217;s a fun vibe at VTM, although I wish it were longer than 2 days, and Seattle is great in April, so this is a great opportunity to meet and hang out with other iOS developers. Since we&#8217;re driving up from Colorado this also offers the opportunity of a road trip across a part of the US that we&#8217;ve never seen.</p>
<p>It&#8217;s not too late to register, and <a href="http://twitter.com/chuckdude/status/50243316301824000">discounts are still available</a>, so, hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2011/03/vtm-seattle-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 4.086 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-06-20 00:45:15 -->

<!-- Compression = gzip -->