<?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 &#187; General</title>
	<atom:link href="http://blog.mundue.net/category/general/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mundue.net</link>
	<description>Indie iPhone Development</description>
	<lastBuildDate>Sat, 03 Sep 2011 23:20:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<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>0</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>
		<item>
		<title>Unsung Heroes</title>
		<link>http://blog.mundue.net/2010/12/unsung-heroes/</link>
		<comments>http://blog.mundue.net/2010/12/unsung-heroes/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 04:00:00 +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=336</guid>
		<description><![CDATA[Last weekend I had the privilege to be able to attend the inaugural 360MacDev conference in Denver. While many readers may only be beginning to think about deploying apps on OS X, there are many developers out there who&#8217;ve been happily making a living doing so for years. The overlap, or synergy, if you will, [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float: left;" title="360Logo.png" src="http://blog.mundue.net/wp-content/uploads/2010/12/appstore360Logo.png" border="0" alt="360Logo.png" hspace="10" width="143" height="59" /></p>
<p>Last weekend I had the privilege to be able to attend the inaugural <a href="http://www.360macdev.com">360MacDev</a> conference in Denver. While many readers may only be beginning to think about deploying apps on OS X, there are many developers out there who&#8217;ve been happily making a living doing so for years. The overlap, or synergy, if you will, of the iOS and OS X communities was clearly evident at the conference.</p>
<p><span id="more-336"></span></p>
<p>Since this was the first 360MacDev it was small and everybody sat in on the same sessions. There was a great mix of in-depth technical talks, design talks, app store talks, and a few of <a href="http://twitter.com/bmf">Mike Lee</a>&#8216;s dirty jokes to kick things off. If you couldn&#8217;t attend be sure to look for the next one in 2011. We got to spend some time with old friends and make a few new ones, and it was nice to see the young crowd (12 year olds Charlie and Santiago) again in attendance. Hate to think what I was doing at that age. It&#8217;s hard to pick, but one of my favorite sessions was <a href="http://www.positivespinmedia.com/">John Pannell</a>&#8216;s <em>Get Connected!</em> talk about the various network capabilities on OS X.</p>
<p>Yes, there was a lot of speculation and trepidation about the upcoming Mac App Store. Fact is, we don&#8217;t have many real answers yet, but in a few short months all will become clear. <a href="http://twitter.com/macguitar">Michael Simmons</a> covered what we know from previous experience on the iTunes App Store and existing Mac sales channels. According to Jay Freeman there will be a <a href="http://www.tuaw.com/2010/12/10/360-macdev-jay-saurik-freeman-on-the-jailbreak-store-for-mac/">Cydia Mac Store</a> for those that aren&#8217;t interested or able to get their Mac apps past the Apple approval process. It&#8217;s not hard to imagine that he&#8217;ll be just as successful in an environment where the devices have never been incarcerated in the first place.</p>
<p>Putting together such an event is slightly more complicated that renting hotel rooms and selling tickets. That&#8217;s where credit is due to <a href="http://twitter.com/jwilker">John</a> and <a href="http://twitter.com/mrs360idev">Nicole</a> Wilker, creators of the 360 Conferences empire. They&#8217;re able to consistently attract top speakers and keynoters, which makes attending a no-brainer for me. Sure, I live in Colorado, which means I didn&#8217;t have to fly to Denver. But I know it was well worth it, even for my friends that had to fly there. Because their focus is the community itself, these smaller 360 conferences are much more personal, and have no &#8220;corporate&#8221; feel.</p>
<p>That&#8217;s why it&#8217;s nice to see John get <a href="http://www.cobizmag.com/articles/colorados-top-25-most-influential-young-professionals/page-6/">recognized as an influential young Coloradan</a>. The work he and Nicole do is much appreciated by the Mac and iPhone developer community. John&#8217;s pretty low-key, he&#8217;d probably rather be sitting in attendance with the rest of us than running around attending to details. Glad they are up to the task. Job well done!</p>
<p style="font-family: 'Lucida Grande';">&#8212;-</p>
<div style="font-family: 'Lucida Grande';"><span style="font-family: 'Lucida Grande';"><strong><span style="font-weight: normal;"><span style="font-family: arial, verdana, tahoma, sans-serif; font-size: 13px; line-height: 20px;"><em>﻿This post is part of <a style="text-decoration: none; color: #004199; padding: 0px; margin: 0px;" href="http://idevblogaday.com/">iDevBlogADay</a>, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the <a style="text-decoration: none; color: #004199; padding: 0px; margin: 0px;" href="http://idevblogaday.com/">web site</a>, <a style="text-decoration: none; color: #004199; padding: 0px; margin: 0px;" href="http://feeds.feedburner.com/idevblogaday">RSS feed</a>, or <a style="text-decoration: none; color: #004199; padding: 0px; margin: 0px;" href="http://twitter.com/#search?q=%23idevblogaday">Twitter</a>.</em></span></span></strong></span></div>
<div style="font-family: 'Lucida Grande';"><span style="font-family: 'Lucida Grande';"><strong><span style="font-weight: normal;"><span style="font-family: arial, verdana, tahoma, sans-serif; font-size: 13px; line-height: 20px;"><em><br />
</em></span></span></strong></span></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.mundue.net/2010/12/unsung-heroes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

