<?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>MKBlog &#187; Coding</title>
	<atom:link href="http://blog.mugunthkumar.com/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mugunthkumar.com</link>
	<description>iPhone, iPad, Windows Phone Development and Usability Guidelines</description>
	<lastBuildDate>Mon, 30 Jan 2012 02:54:37 +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>iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit</title>
		<link>http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/</link>
		<comments>http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 04:30:29 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[ios 5]]></category>
		<category><![CDATA[mknetworkkit]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1485</guid>
		<description><![CDATA[If you have been following me on Twitter or reading MKBlog, you would already be knowing about MKNetworkKit. I wrote a introductory post on MKNetworkKit couple of months ago and later explained in a more detailed post on how to use it in other sophisticated scenarios. From feedback so far, Image Caching was one aspect [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/' rel='bookmark' title='iOS Tutorial: Advanced Networking with MKNetworkKit'>iOS Tutorial: Advanced Networking with MKNetworkKit</a> <small>Couple of weeks ago, I wrote a clean, fast networking...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>If you have been <a href="http://twitter.com/mugunthkumar">following me on Twitter</a> or reading MKBlog, you would already be knowing about MKNetworkKit.</p>
<p>I wrote a <a href="http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/">introductory post on MKNetworkKit</a> couple of months ago and later explained in a <a href="http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/">more detailed post</a> on how to use it in other sophisticated scenarios.</p>
<p>From feedback so far, Image Caching was one aspect of MKNetworkKit that developers didn&#8217;t understand pretty well. In this post, I&#8217;ll try to explain how to use MKNetworkKit for image caching and loading thumbnails.<br />
Thumbnails are often used in iOS apps to load friend&#8217;s avatar pictures from a Facebook feed or flickr thumbnails for a given tag and in many similar cases.</p>
<p>MKNetworkEngine makes it a breeze to add this feature into your app. What not? With MKNetworkKit, you will even know if the response image is from cache or loaded for the first time. Using this information, you can &#8220;fade in&#8221; your thumbnails when you load the images for the first time (like in Apple&#8217;s <a href="http://itunes.apple.com/us/app/itunes-movie-trailers/id471966214?mt=8">iTunes Movie Trailers</a> app).</p>
<p>The completed example looks like this.</p>
<div class="wp-caption aligncenter" style="width: 331px"><img style="border-style: initial; border-color: initial; border-width: 0px;" title="iOS Simulator.png" src="http://blog.mugunthkumar.com/wp-content/uploads/iOS-Simulator.png" alt="IOS Simulator" width="321" height="600" border="0" /><p class="wp-caption-text">Screenshot showing images loaded asynchronously using MKNetworkKit</p></div>
<p style="text-align: left;">Having said that, lets get our hands dirty with some real code. In this example, I&#8217;ll show you how to load images from Flickr on a table view controller asynchronously.</p>
<h3>Step 1: Create a Flickr Engine</h3>
<p>Easy peasy. Create a subclass of MKNetworkEngine and let&#8217;s name it as &#8220;FlickrEngine&#8221;. Initialize your flickr engine with api.flickr.com as hostname in your application delegate.</p>
<h3>Step 2: Create a custom cache directory for storing the cached Flickr thumbanils</h3>
<p>Override cacheDirectoryName and return a custom directory for storing the cached thumbnails.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> cacheDirectoryName <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>paths <span style="color: #002200;">=</span> NSSearchPathForDirectoriesInDomains<span style="color: #002200;">&#40;</span>NSCachesDirectory, NSUserDomainMask, <span style="color: #a61390;">YES</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>documentsDirectory <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paths objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>cacheDirectoryName <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>documentsDirectory stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;FlickrImages&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> cacheDirectoryName;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This step is optional. But, since thumbnails can easily occupy precious disk space, you might want to clear them at periodic intervals. MKNetworkEngine provides a handy method (emptyCache) to empty the cache directory for a specific engine. The default implementation of this method removes all files within the cache directory of that engine. If you don&#8217;t override cacheDirectoryName and provide a distinct cache directory for your engine, you will end up emptying the shared cache directory, when you call emptyCache.</p>
<h3>Step 3: Write a method to list flickr images for a specified tag</h3>
<p>By now, you already know that creating a network request using MKNetworkKit is a no-brainer. The following shows how to create a request for loading images for a given tag.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> imagesForTag<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> tag onCompletion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>FlickrImagesResponseBlock<span style="color: #002200;">&#41;</span> imageURLBlock onError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MKNKErrorBlock<span style="color: #002200;">&#41;</span> errorBlock <span style="color: #002200;">&#123;</span>
&nbsp;
    MKNetworkOperation <span style="color: #002200;">*</span>op <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self operationWithPath<span style="color: #002200;">:</span>FLICKR_IMAGE_URL<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>tag urlEncodedString<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>op onCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span>MKNetworkOperation <span style="color: #002200;">*</span>completedOperation<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>response <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>completedOperation responseJSON<span style="color: #002200;">&#93;</span>;
        imageURLBlock<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>response objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;photos&quot;</span><span style="color: #002200;">&#93;</span> objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;photo&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span> onError<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        errorBlock<span style="color: #002200;">&#40;</span>error<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>self enqueueOperation<span style="color: #002200;">:</span>op<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>The FLICKR_IMAGE_URL macro is defined as</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define FLICKR_IMAGE_URL(__TAG__) [NSString stringWithFormat:@&quot;services/rest/?method=flickr.photos.search&amp;amp;api_key=%@&amp;amp;tags=%@&amp;amp;per_page=200&amp;amp;format=json&amp;amp;nojsoncallback=1&quot;, FLICKR_KEY, __TAG__]</span></pre></div></div>

<p>Note that, the host name api.flickr.com gets prefixed automatically when you create operations on this engine.</p>
<p>You should generate a new flickr api key and replace it in the FLICKR_KEY macro. You can create one for free <a href="http://www.flickr.com/services/apps/create/apply">here.</a> (For running the example, you can use my key)</p>
<h3>Step 4: Create a custom table view cell for loading flickr images</h3>
<p>In this custom cell, write a method setFlickrData: that updates the cell from the dictionary you receive by invoking the flickr REST API</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setFlickrData<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> thisFlickrImage <span style="color: #002200;">&#123;</span>
&nbsp;
    self.titleLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;title&quot;</span><span style="color: #002200;">&#93;</span>;
	self.authorNameLabel.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;owner&quot;</span><span style="color: #002200;">&#93;</span>;
    self.loadingImageURLString <span style="color: #002200;">=</span>
    <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://farm%@.static.flickr.com/%@/%@_%@_s.jpg&quot;</span>,
     <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;farm&quot;</span><span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;server&quot;</span><span style="color: #002200;">&#93;</span>,
     <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;id&quot;</span><span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>thisFlickrImage objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;secret&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    self.imageLoadingOperation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>ApplicationDelegate.flickrEngine imageAtURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span>self.loadingImageURLString<span style="color: #002200;">&#93;</span>
                                    onCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span>fetchedImage, <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>url, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
                                        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self.loadingImageURLString isEqualToString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>url absoluteString<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                                                self.thumbnailImage.image <span style="color: #002200;">=</span> fetchedImage;
                                    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<blockquote><p>Tip: Avoid setting the individual labels of a table view cell in the cellForRowAtIndexPath: method. It makes the cell less portable across your other view controllers.</p></blockquote>
<p>Carefully note the use of the variable self.loadingImageURLString. If you don&#8217;t save the loading image&#8217;s URL in an ivar, your images will continue to be updated when the previous operation completes. To circumvent this, either cancel the operation when a cell is reused, or check if the returned URL is the original URL that was loaded for this cell (by storing it in ivar).</p>
<p>As on <a href="https://github.com/MugunthKumar/MKNetworkKit/commit/b9ba2d6501b498e837abf49cb999dbbd67b30a4f">this commit</a>, MKNetworkEngine&#8217;s imageAtURL method will return you the actual operation created. You should retain this and cancel it when not necessary.</p>
<h3>Step 5: Clear previously loaded images if the cell will be reused</h3>
<p>You should clear previously loaded images by overriding prepareForReuse method. It&#8217;s a one-liner.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> prepareForReuse <span style="color: #002200;">&#123;</span>
&nbsp;
    self.thumbnailImage.image <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>self.imageLoadingOperation cancel<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>If you don&#8217;t write this, you will see old images on the cell while the new image is being loaded.<br />
Instead of &#8220;nil&#8221; you can also show a default placeholder image here.</p>
<p>You should also consider canceling the old imageLoadingOperation so as to load the latest visible cells faster. If you don&#8217;t cancel the operation, when the user scrolls fast to the bottom of the list, the engine loads all the images from the first cell (including images for cells that are now hidden and reused) and there by slowing down the image load operation for the currently visible cell. You can test this from the code by commenting it out and checking the performance.</p>
<h3>Step 6: Fade in thumbnails like the Apple trailers app</h3>
<p>MKNetworkEngine&#8217;s imageAtURL method returns the image in a block method. The block method, onCompletion looks like this.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span>fetchedImage, <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>url, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
                                        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self.loadingImageURLString isEqualToString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>url absoluteString<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                                                self.thumbnailImage.image <span style="color: #002200;">=</span> fetchedImage;
                                    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>If the variable isInCache is false, you can &#8220;fade in&#8221; the image so as to add a nice UI touch to your app. The following code block illustrates this.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span>fetchedImage, <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>url, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
                                        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self.loadingImageURLString isEqualToString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>url absoluteString<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
                                            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                                                self.thumbnailImage.image <span style="color: #002200;">=</span> fetchedImage;
                                            <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
                                                UIImageView <span style="color: #002200;">*</span>loadedImageView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIImageView alloc<span style="color: #002200;">&#93;</span> initWithImage<span style="color: #002200;">:</span>fetchedImage<span style="color: #002200;">&#93;</span>;
                                                loadedImageView.frame <span style="color: #002200;">=</span> self.thumbnailImage.frame;
                                                loadedImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
                                                <span style="color: #002200;">&#91;</span>self.contentView addSubview<span style="color: #002200;">:</span>loadedImageView<span style="color: #002200;">&#93;</span>;
&nbsp;
                                                <span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0.4</span>
                                                                 animations<span style="color: #002200;">:^</span>
                                                 <span style="color: #002200;">&#123;</span>
                                                     loadedImageView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
                                                     self.thumbnailImage.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
                                                 <span style="color: #002200;">&#125;</span>
                                                                 completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> finished<span style="color: #002200;">&#41;</span>
                                                 <span style="color: #002200;">&#123;</span>
                                                     self.thumbnailImage.image <span style="color: #002200;">=</span> fetchedImage;
                                                     self.thumbnailImage.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
                                                     <span style="color: #002200;">&#91;</span>loadedImageView removeFromSuperview<span style="color: #002200;">&#93;</span>;
                                                 <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
                                            <span style="color: #002200;">&#125;</span>
                                        <span style="color: #002200;">&#125;</span>
                                    <span style="color: #002200;">&#125;</span></pre></div></div>

<h2>Source Code</h2>
<p>The complete source code is available as a demo on <a href="https://github.com/MugunthKumar/MKNetworkKit">MKNetworkKit&#8217;s Github repository</a>.<br />
&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1485_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1485?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1485_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1485&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="iOS+Tutorial%3A+Image+Cache+and+Loading+Thumbnails+using+MKNetworkKit" data-count="horizontal" data-text="iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit" data-url="http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/' rel='bookmark' title='iOS Tutorial: Advanced Networking with MKNetworkKit'>iOS Tutorial: Advanced Networking with MKNetworkKit</a> <small>Couple of weeks ago, I wrote a clean, fast networking...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>iOS Tutorial: Advanced Networking with MKNetworkKit</title>
		<link>http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/</link>
		<comments>http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 11:00:13 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[mknetworkkit]]></category>
		<category><![CDATA[nsmutableurlrequest]]></category>
		<category><![CDATA[nsurlconnection]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1411</guid>
		<description><![CDATA[Couple of weeks ago, I wrote a clean, fast networking toolkit for iOS and Mac written for the LLVM Compiler 3.0 with ARC. Reception was very good that it was the &#8220;most-watched&#8221; repository on Github last week. Early adopters have sent me innumerable emails on how fast their network operations are, and how responsive their [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/' rel='bookmark' title='iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit'>iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit</a> <small>If you have been following me on Twitter or reading...</small></li>
<li><a href='http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/' rel='bookmark' title='iOS Framework: Introducing MKNetworkKit'>iOS Framework: Introducing MKNetworkKit</a> <small>How awesome would it be if a networking framework automatically...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>Couple of weeks ago, I wrote a <a href="http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/">clean, fast networking toolkit for iOS and Mac</a> written for the LLVM Compiler 3.0 with ARC.<br />
Reception was very good that it was the &#8220;most-watched&#8221; repository on Github last week. Early adopters have sent me innumerable emails on how fast their network operations are, and how responsive their app is after integrating MKNetworkKit.<br />
MKNetworkKit is faster (and it makes your app feel smoother and faster with seamless transparent caching) in reality. There are two things that makes MKNetworkKit faster.<br />
First, it&#8217;s ARC based and the awesome LLVM 3.0 compiler brings in a ton of performance benefits. Using the @autoreleasepool block instead of NSAutoReleasePool in MKNetworkOperation alone should improve the performance by a huge factor (Apple claims it to be 6 times faster). If you still haven&#8217;t migrated to ARC because you want to support those iOS 3.x users, read <a href="http://mattgemmell.com/2011/12/05/latest-version/">this post</a> by Matt Gemmell first.</p>
<p>Second important performance benefit is seamless and transparent caching. By transparent caching, I mean, caching that involves zero overhead from the developer (That&#8217;s you).</p>
<p>Let me, in this post, brief you about how this seamless caching might help you. First, an example. You are refreshing a twitter stream. A GET request for that looks similar to</p>
<p>GET http://twitter.com/mugunthkumar/statuses</p>
<h2>Caching your responses, the wrong way</h2>
<p>Some developers cache responses using Core Data. <strong>STOP IT</strong></p>
<blockquote><p>Using Core Data for caching is like using the military to kill bedbugs in your bedroom. DON&#8217;T DO IT.</p></blockquote>
<p>The problem when you implement Core Data is, you should program your view controllers to work with two kinds of data structures. One, JSON/XML from server and the other, Core Data NSManagedObjects. Some &#8220;clever&#8221; developers &#8220;take it to the next level&#8221; by just programming their view controllers to work with only Core Data. The design goes like this. The network layer talks to the server and updates Core Data Store. Once the store is updated, send a NSNotification to &#8220;refresh&#8221; view controllers.<br />
This may sound clever to many. But it&#8217;s completely WRONG. I REPEAT. COMPLETELY WRONG. Core Data (or even structured SQL storage) is not meant for that. Core Data is a structured storage for persisting/serializing Object graphs in your application. Don&#8217;t use it for storing objects that have a low life time. Thumbnail images, list of tweets etc., just don&#8217;t belong there. Secondly, this would require you to read and write to flash memory on the iDevice which have a limited read/write cycle. Finally, reading and writing to disk (in this case, Core Data) is a very ugly way to transfer data from one class to another (in this case, from your Network Layer to View Controllers)</p>
<h2>Say hello to MKNetworkKit</h2>
<p>MKNetworkKit calls the SAME completion handler with cached data if you are making the call for the second time. When the network connectivity is proper, MKNetworkKit calls your completion handler twice. First with the cached data and again after fetching the latest data from server. As such, you can design your view controllers to work with just ONE kind of data, data from server. If you have an app that doesn&#8217;t cache and doesn&#8217;t work offline, just replace your networking library with MKNetworkKit and you get caching for free. Not even a single line of code change is required on your view controllers. Caching is transparent. Your view controllers needs to work with the same data structure, no matter whether the data is from cache or server.</p>
<h3>Behind the scenes</h3>
<p>MKNetworkKit caching is super light-weight and it caches your responses in a NSMutableDictionary. Doesn&#8217;t that lead to high memory usage? Yes. of-course, but MKNetworkKit is clever. It observes the UIApplicationDidReceiveMemoryWarningNotification and flushes the dictionary to disk. The next time you make a request to the cached URL, the cached data is brought back to memory. So in-effect, it has a in-memory cache and disk cache and uses a least recently used algorithm to flush items to disk. The MKNetworkEngine class has methods that can be over-ridden to control the cache cost.</p>
<p>Just override the method</p>

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

<p>and return a higher/lower value based on your application&#8217;s requirements.</p>
<p>MKNetworkKit caching works like a intermediate proxy server by intercepting the response headers. So, when a second GET request to the same URL is made, MKNetworkKit behaves the following way.</p>
<p>1) For GET requests that sent a ETag in the header previously (for example, requests to Amazon S3 servers), MKNetworkKit sends a second request as a HEAD request (even if you specify as GET) with IF-NONE-MATCHheader. Most servers that send ETag (like Amazon S3) responds to IF-NONE-MATCH by sending the real data only when it has been changed. Otherwise, they return a 304 Not Modified which MKNetworkKit safely ignores. So data transfer is really not huge. Even this request is honored only after 1 day. So, repeated requests to the same thumbnail image doesn&#8217;t even hit the server.</p>
<p>2) For any GET request that contained a Cache-Control:max-age=in the header, MKNetworkKit honors that and makes the second request only after the expiry date. For dynamically generated requests, you should set Cache-Control on server. This not only helps MKNetworkKit, but most proxy servers along the way.</p>
<p>3) For requests that contained a Last-Modified field in the header, MKNetworkKit sends a &#8220;IF-MODIFIED-SINCE&#8221; HEAD request. This again works like the IF-NONE-MATCH. The server, either sends the complete data or a 304 Not Modified.</p>
<p>4) For servers that implement Cache-Control: no-cache, MKNetworkKit goes one step ahead and makes a second request only after a minute (60 sec). So repeated refreshes to often refreshed page will not exactly hit the server. For example, refreshing foursquare check-ins. It&#8217;s rare for these information to change within the next 60 sec.</p>
<p>5) For performance reasons, when the response type is an image, and the response headers doesn&#8217;t have any cache control information, MKNetworkKit assumes an expiry date of 7 days.</p>
<p>The last two are not an RFC standard. But these optimizations make network operations fast on a mobile devices even if the server isn&#8217;t implemented in an optimized way. All POST, PUT, HEAD and DELETE requests are ignored and not cached.</p>
<p>And, of course, you can customize all these behaviors by editing the values in MKNetworkKit.h</p>
<h2>Freezing Operations</h2>
<p>Another very important feature of MKNetworkKit is operation freezing. Imagine that, your customer take an awesome photo with your own &#8220;Instagram-killer&#8221; app, but since he is at a remote exotic place, 3G connectivity is poor and uploading the photo fails. Without MKNetworkKit, you should remember the photo related meta data, store the photo&#8217;s NSData in a file and upload the operation the next time the app is launched. Painful!<br />
With MKNetworkKit, you mark the photo upload operation is &#8220;freezable&#8221;. This means, in the event of network failure, your operations are automatically serialized (frozen beneath snow) and restored the next time the app launches, all for free.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">MKNetworkOperation <span style="color: #002200;">*</span>op <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>myEngine operationWithPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/imageUpload&quot;</span> params<span style="color: #002200;">:</span>paramsDict httpMethod<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;POST&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>op setFreezable<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// ONE EXTRA LINE</span>
<span style="color: #002200;">&#91;</span>myEngine enqueOperation<span style="color: #002200;">:</span>op<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>You can mark any POST/PUT/DELETE operation as freezable. GET operations are not freezable and MKNetworkKit ignores your call to setFreezable: if your operation is a &#8220;GET&#8221; operation.</p>
<h2>Advanced Tips</h2>
<h3>Friction-free authentication</h3>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">MKNetworkOperation <span style="color: #002200;">*</span>op <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>myEngine operationWithPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/letmein&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>op setUserName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mugunth&quot;</span> password<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mYsEkReTpAsSwOrD&quot;</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// ONE EXTRA LINE</span>
<span style="color: #002200;">&#91;</span>op setUserName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mugunth&quot;</span> password<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mYsEkReTpAsSwOrD&quot;</span> basicAuth<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// OR THIS LINE</span>
<span style="color: #002200;">&#91;</span>myEngine enqueOperation<span style="color: #002200;">:</span>op<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>When your server uses HTTP Basic auth or Digest auth or even Windows NTLM authentication, all you need to do is to set your username and password and MKNetworkKit auto-magically authenticates your request!. For NTLM authentication, just ensure your username is &#8220;domain\username&#8221;. There is no separate method setDomain: or something.</p>
<p>You can also set basicAuth:YES to send the credentials even before receiving the authentication challenge. However, this works only if your server uses HTTP Basic Authentication.</p>
<h3>Custom Authentication</h3>
<p>If your server uses HTML Form authentication, you can override the authHandler block and provide custom auth mechanisms.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">MKNetworkOperation <span style="color: #002200;">*</span>op <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>myEngine operationWithPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/letmein&quot;</span><span style="color: #002200;">&#93;</span>;
op.authHandler <span style="color: #002200;">=</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURLAuthenticationChallenge</span> <span style="color: #002200;">*</span>cred<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span> 
<span style="color: #11740a; font-style: italic;">// show a web view controller or do whatever you want and finally, when you have a credentials ready, just call </span>
<span style="color: #002200;">&#91;</span>challenge.sender useCredential<span style="color: #002200;">:</span>credential forAuthenticationChallenge<span style="color: #002200;">:</span>challenge<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>;
<span style="color: #002200;">&#91;</span>myEngine enqueOperation<span style="color: #002200;">:</span>op<span style="color: #002200;">&#93;</span>;</pre></div></div>

<h3>Overriding MKNetworkEngine</h3>
<p>Tweaking the URL building methods with MKNetworkEngine is easy. Let me start by giving you an example. Imagine that you have a server which authenticates a logged in user and after authentication, it expects a Authorization header to be set with an access token.<br />
You need to have a <a href="http://en.wikipedia.org/wiki/Factory_method_pattern">factory method</a> that creates URLs customized to your web service. This could include adding a authorization header in our case. You can do this by overriding the method,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> enqueueOperation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MKNetworkOperation<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> operation;</pre></div></div>

<p>For example, in the above case, you can check your engine subclass for an access token and add it to the operation&#8217;s header in this method (if you have one).</p>
<h3>Overriding MKNetworkOperation</h3>
<p>Sometimes, you might do custom error handling based on the response from your server. For example, your server might send a valid HTTP response (status code 200) which could be an internal error, like &#8220;Invalid User&#8221;. Business logic errors are better handled with your own application level error codes. You overriding MKNetworkOperation to customize the success/failure reporting. I would highly recommend doing this along with designing your server to send error codes for error conditions.</p>
<p>The following methods are to be overridden for customizing error handling.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> operationSucceeded;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> operationFailedWithError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSError</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> error;</pre></div></div>

<p>For example, in the previous case, you can override operationSucceeded, inspect the response and if the response was indeed a business logic error (&#8220;Invalid User&#8221;), you can call the [super operationFailedWithError:[Your custom error class for "Invalid User"]];<br />
Otherwise, call [super operationSucceeded].</p>
<p>You can also override operationFailedWithError to introspect the actual cause of the error, if your server sends any error related information in the dictionary.</p>
<p>The reason for overriding at this level is to minimize error handling at view controller layer. So your presentation layer, UIViewController subclasses will be cleaner to read.</p>
<p>If you have subclassed the MKNetworkOperation and want the factory method in your engine subclass, operationWithURLString:params:httpMethod to prepare an operation of your subclass. To register your operation subclass with the engine, you can call the registerOperationSubclass: method.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> registerOperationSubclass<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">Class</span><span style="color: #002200;">&#41;</span> aClass;</pre></div></div>

<p>Your code fragment might look like,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self.myEngine registerOperationSubclass<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>MyAppNetworkOperation class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<h3>Image Cache with MKNetworkEngine</h3>
<p>MKNetworkEngine has a handy method to load images from a server. It&#8217;s built-in cache mechanism ensures, your images are cached without using any third-party image cache libraries. That means your code base is even leaner.<br />
You can use the following method of MKNetworkEngine to load images.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> imageAtURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>url onCompletion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MKNKImageBlock<span style="color: #002200;">&#41;</span> imageFetchedBlock;</pre></div></div>

<p>MKNKImageBlock is defined like this.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">typedef</span> <span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span>MKNKImageBlock<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#40;</span>UIImage<span style="color: #002200;">*</span> fetchedImage, <span style="color: #400080;">NSURL</span><span style="color: #002200;">*</span> url, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span>;</pre></div></div>

<p>So your calling code will look like,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">    <span style="color: #002200;">&#91;</span>ApplicationDelegate.myAppEngine imageAtURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://example.com/image.png&quot;</span><span style="color: #002200;">&#93;</span> onCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span>fetchedImage, <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>fetchedURL, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        self.imageView.image <span style="color: #002200;">=</span> fetchedImage;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>If you are loading images onto a imageView inside a tableview cell, you can check if the completed URL is same as the passed URL</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">    <span style="color: #002200;">&#91;</span>ApplicationDelegate.myAppEngine imageAtURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://example.com/image.png&quot;</span><span style="color: #002200;">&#93;</span> onCompletion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span>UIImage <span style="color: #002200;">*</span>fetchedImage, <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>fetchedURL, <span style="color: #a61390;">BOOL</span> isInCache<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>originalURL <span style="color: #002200;">==</span> fetchedURL<span style="color: #002200;">&#41;</span>
        cell.imageView.image <span style="color: #002200;">=</span> fetchedImage;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>This check is necessary as tableview cells might be recycled and a cell might end up getting images from multiple network operations.</p>
<p>You might also want to read my other elaborate post on <a href="http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/">Image Caching with MKNetworkKit</a></p>
<p>Lastly, if you are fading in your images like those fancy apps, add your fade-in logic if the image is loaded from server and not from cache.</p>
<h2>Source Code</h2>
<p><a href="https://github.com/MugunthKumar/MKNetworkKit">MKNetworkKit</a> on Github</p>
<p>MKNetworkKit might look simple, but it&#8217;s incredibly powerful. Use it in your apps and tell me how it scores. My next blog post would be on how to write a better RESTful server that serves a mobile device. Watch this space, subscribe to <a href="http://feeds.feedburner.com/MugunthKumar">my feed</a> or <a href="http://twitter.com/MugunthKumar">follow me on twitter</a>.</p>
<p>Interested in learning in-depth features of Objective-C and iOS? You should get my book.</p>
<p>Amazon - <a href="http://mk.sg/ios5book">http://mk.sg/ios5book<br />
</a></p>
<p>iBooks - <a href="http://mk.sg/ibook">http://mk.sg/ibook</a></p>
<p>Wiley &#8211; <a href="http://mk.sg/book">http://mk.sg/book</a></p>
<p>Book Depository &#8211; <a href="http://mk.sg/bdbook">http://mk.sg/bdbook</a><br />
&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1411_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1411?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1411_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1411&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-advanced-networking-with-mknetworkkit%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="iOS+Tutorial%3A+Advanced+Networking+with+MKNetworkKit" data-count="horizontal" data-text="iOS Tutorial: Advanced Networking with MKNetworkKit" data-url="http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-advanced-networking-with-mknetworkkit%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-advanced-networking-with-mknetworkkit%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/ios-tutorial-image-cache-and-loading-thumbnails-using-mknetworkkit/' rel='bookmark' title='iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit'>iOS Tutorial: Image Cache and Loading Thumbnails using MKNetworkKit</a> <small>If you have been following me on Twitter or reading...</small></li>
<li><a href='http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/' rel='bookmark' title='iOS Framework: Introducing MKNetworkKit'>iOS Framework: Introducing MKNetworkKit</a> <small>How awesome would it be if a networking framework automatically...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/ios-tutorial-advanced-networking-with-mknetworkkit/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code</title>
		<link>http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/</link>
		<comments>http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/#comments</comments>
		<pubDate>Sun, 20 Nov 2011 05:33:32 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ios 5]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1308</guid>
		<description><![CDATA[Just wrote this class, MKiCloudSync (100 lines of code) that auto syncs your NSUserDefaults to iCloud. How to use? All you need to do is to enable iCloud key value store entitlements, copy the files and forget about the rest. Step 1: Enable iCloud entitlements for your app. This is easily done in Xcode 4.2.1 [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/' rel='bookmark' title='Using MKStoreKit in your apps'>Using MKStoreKit in your apps</a> <small>MKStoreKit, as you probably know is a framework for implementing...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>Just wrote this class, MKiCloudSync (100 lines of code) that auto syncs your NSUserDefaults to iCloud.</p>
<h2>How to use?</h2>
<p>All you need to do is to enable iCloud key value store entitlements, copy the files and forget about the rest.</p>
<p><strong>Step 1:</strong></p>
<p>Enable iCloud entitlements for your app. This is easily done in Xcode 4.2.1 by opening your target settings and checking &#8220;Enable Entitlements&#8221; from the summary tab.</p>
<p>This is illustrated below.</p>
<p><div class="wp-caption aligncenter" style="width: 610px"><img style="border-style: initial; border-color: initial; border-width: 0px;" title="Xcode.png" src="http://blog.mugunthkumar.com/wp-content/uploads/Xcode.png" alt="Xcode" width="600" height="378" border="0" /><p class="wp-caption-text">Enabling iCloud Entitlements in Xcode 4.2.1</p></div><br />
<strong>Tip: </strong><br />
If you are sharing settings with other apps, ensure that your iCloud Key-Value Store is the same across all those apps.<br />
<strong>Step 2:</strong><br />
Drag the two files</p>
<ul>
<li>MKiCloudSync.h</li>
<li>MKiCloudSync.m </li>
</ul>
<p>into your project. You can find these files in the Source Code section of this post.<br />
<strong>Step 3:</strong><br />
In your applicationDidFinishLaunchingWithOptions: method,<br />
start the sync by calling,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>MKiCloudSync start<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>You also have to #include the header file.<br />
This is probably the only line of code you have to write!<br />
<strong>Step 4:</strong><br />
Sleep… Kidding.</p>
<p>There is no step 4. Continue using NSUserDefaults to save your settings. The MKiCloudSync class automatically syncs your settings to iCloud and restores them back to your NSUserDefaults when they are changed on other devices.</p>
<p>To top them all, it also posts a notification,</p>
<pre>kMKiCloudSyncNotification</pre>
<p>to let you know that a sync has been performed. You can listen to this notification and update your user interface from NSUserDefaults.</p>
<h2>Advantages</h2>
<ul>
<li>Upgrading your existing iOS 4 apps to sync settings to iCloud is now super easy.</li>
<li>With this class, you no longer have to add calls to NSUbiquitousKeyValueStore throughout your app. You can continue your existing method of saving them to NSUserDefaults. Everything is automatic. If your settings might change often, you can observe the notification <strong><em>kMKiCloudSyncNotification</em></strong> and update your user interface.</li>
</ul>
<h2>Source Code</h2>
<ul>
<li><a href="https://github.com/MugunthKumar/MKiCloudSync">MKiCloudSync on Github</a>
</ul>
<h2>Licensing</h2>
<p>Royalty free for commercial or non-commercial use, though attribution will please me to write more such code <img src='http://blog.mugunthkumar.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1308_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1308?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1308_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1308&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="iOS+Code%3A+MKiCloudSync+%26%238211%3B+Sync+your+NSUserDefaults+to+iCloud+with+a+single+line+of+code" data-count="horizontal" data-text="iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code" data-url="http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/' rel='bookmark' title='Using MKStoreKit in your apps'>Using MKStoreKit in your apps</a> <small>MKStoreKit, as you probably know is a framework for implementing...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Easy Debugging with NSMutableURLRequest</title>
		<link>http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/</link>
		<comments>http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 11:30:36 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[description]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[nsmutableurlrequest]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[tip]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1291</guid>
		<description><![CDATA[This post is a sequel to one of my previous post, Easy Debugging with ASIHTTPRequest. I previously showed you a code snippet for logging ASIHTTPRequest as curl commands on command line. I&#8217;ve updated that code for NSMutableURLRequest, which means, you can use it for almost any third party networking kits, including the recently famous AFNetworking. [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/' rel='bookmark' title='Easy Debugging with ASIHTTPRequest'>Easy Debugging with ASIHTTPRequest</a> <small>Just wrote this quick and dirty method that dumps a...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>This post is a sequel to one of my previous post, <a href="http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/">Easy Debugging with ASIHTTPRequest</a>.<br />
I previously showed you a code snippet for logging ASIHTTPRequest as curl commands on command line.<br />
I&#8217;ve updated that code for NSMutableURLRequest, which means, you can use it for almost any third party networking kits, including the recently famous AFNetworking.</p>
<h2>The Drive</h2>
<p>The main necessity for this was, I always used to miss some of the parameters I should use for calling a said API. The only way to debug these issues is to simulate the call on a third party REST client, check if everything works and then start coding. But that was a bit too overkill for me. I wrote this snippet so that, you can straight away NSLog a NSMutableURLRequest and see the curl syntax on the console. You can copy and paste this to your Terminal and check if you are calling the API correctly.</p>
<h2>Usage</h2>
<p>Drag the attached files into your project.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">&lt;code&gt;NSMutableURLRequest<span style="color: #002200;">+</span>CurlDescription.h
<span style="color: #400080;">NSMutableURLRequest</span><span style="color: #002200;">+</span>CurlDescription.m&lt;<span style="color: #002200;">/</span>code&gt;</pre></div></div>

<p>Add a line to your PCH file or any global header file to include this file.</p>
<p>That&#8217;s it!. You are done.<br />
Now, whenever you need to print your request as a curl command, just add a NSLog it.</p>
<p>If you are using <a href="https://github.com/gowalla/AFNetworking">AFNetworking</a>, I would recommend overriding the method,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>enqueueHTTPRequestOperationWithRequest<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURLRequest</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>urlRequest 
                                       success<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> object<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>success 
                                       failure<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSHTTPURLResponse</span> <span style="color: #002200;">*</span>response, <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>failure;</pre></div></div>

<p>in your own APIClient class.<br />
You can now NSLog the request and call the super class implementation.</p>
<h2>Example</h2>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> enqueueHTTPRequestOperationWithRequest<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURLRequest</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>request success<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>success failure<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSHTTPURLResponse</span> <span style="color: #002200;">*</span>, <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>failure <span style="color: #002200;">&#123;</span>
&nbsp;
    NSLog<span style="color: #002200;">&#40;</span>request<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>super enqueueHTTPRequestOperationWithRequest<span style="color: #002200;">:</span>request success<span style="color: #002200;">:</span>success failure<span style="color: #002200;">:</span>failure<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This would log every single API call you make in your app on the console as a curl command.<br />
A second advantage of this is, it reduces<em> cognitive overload</em>. When you see the request printed on console, you don&#8217;t have to think what it is doing. Just copy and paste it to Terminal and start debugging right away! </p>
<h2>Source Code </h2>
<p><a href="http://blog.mugunthkumar.com/wp-content/uploads/NSMutableURLRequest+Curl.zip" title="NSMutableURLRequest+Curl.zip" alt="NSMutableURLRequest+Curl">NSMutableURLRequest+Curl.zip</a></p>
<h2>Licensing</h2>
<p>Do whatever you want with the code without removing the source code attribution.</p>
<p>&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1291_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1291?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1291_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1291&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-nsmutableurlrequest%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="Easy+Debugging+with+NSMutableURLRequest" data-count="horizontal" data-text="Easy Debugging with NSMutableURLRequest" data-url="http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-nsmutableurlrequest%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-nsmutableurlrequest%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/' rel='bookmark' title='Easy Debugging with ASIHTTPRequest'>Easy Debugging with ASIHTTPRequest</a> <small>Just wrote this quick and dirty method that dumps a...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS5: Migrating your code to NSJSONSerialization using the Adapter Design Pattern</title>
		<link>http://blog.mugunthkumar.com/coding/ios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern/</link>
		<comments>http://blog.mugunthkumar.com/coding/ios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 03:20:59 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[json-framework]]></category>
		<category><![CDATA[JSONKit]]></category>
		<category><![CDATA[touchJSON]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1169</guid>
		<description><![CDATA[In iOS 5, Apple introduced NSJSONSerialization, for parsing JSON strings. But, as on date, you might have already developed your app using a third party component like JSONKit or json-framework or TouchJSON and you might not want to migrate your complete code base to NSJSONSerialization. In fact removing or replacing an existing framework is not [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>In iOS 5, Apple introduced NSJSONSerialization, for parsing JSON strings.</p>
<p>But, as on date, you might have already developed your app using a third party component like JSONKit or json-framework or TouchJSON and you might not want to migrate your complete code base to NSJSONSerialization. In fact removing or replacing an existing framework is not really an easy thing especially if you have a lot of dependencies. However, moving towards Apple&#8217;s implementation is always safer to use since you have the guarantee that it will be maintained kept up to date.</p>
<h2>The Adapter Design Pattern</h2>
<p>This is where the <a href="http://en.wikipedia.org/wiki/Adapter_pattern">Adapter design pattern</a> comes to rescue.<br />
Adapters are classes that helps in migrating your code base with as low side-effects as possible. If you were depending on the class categories in your third party framework, which is probably the case, you can use my &#8220;adapter&#8221; classes to route those messages to Apple&#8217;s framework. That way, all you need to do is to copy couple of files from my framework, and ditch your third party json parsing frameworks. It should all start working automatically.</p>
<p>Let&#8217;s see how that works.</p>
<p>The adapter classes I wrote &#8220;adapts&#8221; your code to use Apple&#8217;s NSJSONSerialization instead of your third party framework. Did I say that the whole adapter classes run under a hundred lines of code?<br />
For example, if you call JSONValue of json-framework in your code like this,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>jsonString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithContentsOfURL<span style="color: #002200;">:</span>@http<span style="color: #002200;">:</span><span style="color: #11740a; font-style: italic;">//example.com/test.json&quot;];</span>
<span style="color: #002200;">&#91;</span>jsonString JSONValue<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>my adapter routes the &#8220;JSONValue&#8221; extension method to Apple&#8217;s implementation. The adapter classes have similar implementations for every similar category method in the framework.</p>
<h2>Source Code</h2>
<p>The source code is pretty elementary right now and supports only json-framework. and I&#8217;m maintaining them on Github here.</p>
<p><a href="https://github.com/MugunthKumar/third-party-json-adapters">https://github.com/MugunthKumar/third-party-json-adapters</a></p>
<p>Expecting volunteers to write equivalent adapters for other frameworks (especially for frameworks that are slower than Apple&#8217;s)</p>
<p>&#8211;</p>
<p>Mugunth</p>
<p><map name='google_ad_map_1169_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1169?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1169_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1169&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="iOS5%3A+Migrating+your+code+to+NSJSONSerialization+using+the+Adapter+Design+Pattern" data-count="horizontal" data-text="iOS5: Migrating your code to NSJSONSerialization using the Adapter Design Pattern" data-url="http://blog.mugunthkumar.com/coding/ios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/ios5-migrating-your-code-to-nsjsonserializer-using-the-adapter-design-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS Tutorial: Sending In App Tweets</title>
		<link>http://blog.mugunthkumar.com/coding/ios-tutorial-sending-in-app-tweets/</link>
		<comments>http://blog.mugunthkumar.com/coding/ios-tutorial-sending-in-app-tweets/#comments</comments>
		<pubDate>Fri, 21 Oct 2011 15:00:49 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[TwTweetComposeViewController]]></category>
		<category><![CDATA[uikit]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1214</guid>
		<description><![CDATA[In iOS 5, Apple introduced tighter twitter integration with Twitter.framework and Accounts.framework. Most of the latest &#8220;social&#8221; apps out there use some kind of frameworks to send out tweets from their app. With iOS 5, you no longer need to build your code against all these frameworks. iOS 5&#8242;s built in Twitter.framework manages most of [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p></p><p>In iOS 5, Apple introduced tighter twitter integration with Twitter.framework and Accounts.framework.</p>
<p>Most of the latest &#8220;social&#8221; apps out there use some kind of frameworks to send out tweets from their app. With iOS 5, you no longer need to build your code against all these frameworks. iOS 5&#8242;s built in Twitter.framework manages most of these issues automatically. In this tutorial, we will go through how to use the built-in framework to send a tweet.</p>
<h1>Steps</h1>
<p>Note that this tutorial uses screenshots from Xcode 4. By now, you should all be using Xcode 4 and should have uninstalled Xcode 3 completely.</p>
<h2>Step 1: Add the Twitter.framework and Accounts.framework</h2>
<p>Open your target on the project navigator to your target&#8217;s build phase.</p>
<p><img title="TwitterTest - TwitterTest.xcodeproj.png" src="http://blog.mugunthkumar.com/wp-content/uploads/TwitterTest-TwitterTest.xcodeproj.png" alt="TwitterTest  TwitterTest xcodeproj" width="600" height="391" border="0" /></p>
<p>Click the &#8220;Link Binary with Libraries&#8221; section (illustrated above) and expand it. Click the &#8220;+&#8221; button to add a new framework and select &#8220;Twitter.Framework&#8221; to this project.</p>
<h2>Step 2: Weak or Strong?</h2>
<p>If you are planning to support iOS 4 (Doh!, you ought to man), you have to weak-link this framework. Click on Twitter.Framework and change the &#8220;Required&#8221; drop down to &#8220;Optional&#8221;.</p>
<p>If you decided to be hippy and prefer to support only iOS 5 (like the attached source) you can ignore this step.</p>
<h2>Step 3: The TwTweetComposeViewController</h2>
<p>Sending a Tweet is much similar to sending a <a href="http://blog.mugunthkumar.com/coding/iphone-tutorial-in-app-email/">In App email</a> or an <a href="http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/">In App SMS</a></p>
<p>You create an instance of TwTweetComposeViewController, set the tweet you want to send and present it to the user.</p>
<p>Before you can do that, just as in the case of In app Email or SMS, you need to check if the device is capable of sending a In-App Tweet.</p>
<p>There could be two cases when you will not be able to send an in app tweet. First, if the user haven&#8217;t yet updated to iOS 5. Second, if the user haven&#8217;t configured his twitter accounts in the settings page.</p>
<p>The first case will not happen if you are planning to restrict your app to iOS 5. But in case you followed Step 2 and are weak-linking your Twitter.framework, you have to check if the class TwTweetComposeViewController is present using the Objective-C runtime method NSClassFromString.</p>
<p>If it returns nil, return and error, otherwise, call the class method, canSendTweet.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>TWTweetComposeViewController canSendTweet<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        TWTweetComposeViewController <span style="color: #002200;">*</span>controller <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TWTweetComposeViewController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<h2>Step 4: The Meat</h2>
<p>Now let us add some flesh to this by setting the initial text.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>TWTweetComposeViewController canSendTweet<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        TWTweetComposeViewController <span style="color: #002200;">*</span>controller <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TWTweetComposeViewController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&lt;strong&gt; <span style="color: #002200;">&#91;</span>controller setInitialText<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Test Tweet&quot;</span><span style="color: #002200;">&#93;</span>; &lt;<span style="color: #002200;">/</span>strong&gt;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>Optionally you can add hyperlinks or images to your tweets. Added images and hyperlinks are automatically compressed and uploaded for you.<br />
You can do this using the methods,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">        <span style="color: #002200;">&#91;</span>controller addURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://blog.mugunthkumar.com&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>controller addImage<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Test.png&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<h2>Step 5: The Delegate, err completionHander</h2>
<p>In iOS 5, not just the TwTweetComposeViewController, but a lot of similar methods use completionHandler to notify the caller of status instead of delegates. So if you use TwTweetComposeViewController, it means you have to be on a minimum of iOS 4 even if you weak-link your framework.</p>
<p>Contrary to the popular belief, completionHandlers are much more cleaner and easy to understand that delegates. For example, in our case, our completionHandler looks like this</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">        controller.completionHandler <span style="color: #002200;">=</span> <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span>TWTweetComposeViewControllerResult result<span style="color: #002200;">&#41;</span>  <span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #002200;">&#91;</span>self dismissModalViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #a61390;">switch</span> <span style="color: #002200;">&#40;</span>result<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">case</span> TWTweetComposeViewControllerResultCancelled<span style="color: #002200;">:</span>
                    <span style="color: #a61390;">break</span>;
&nbsp;
                <span style="color: #a61390;">case</span> TWTweetComposeViewControllerResultDone<span style="color: #002200;">:</span>
                    <span style="color: #a61390;">break</span>;
&nbsp;
                <span style="color: #a61390;">default</span><span style="color: #002200;">:</span>
                    <span style="color: #a61390;">break</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>;</pre></div></div>

<p>You can add UIAlertViews or similar constructs when tweet sending fails here.</p>
<p>So, that&#8217;s it! Wasn&#8217;t it easier than the traditional methods? Remember oAuth, MGTwitterEngine, xAuth, setting up accounts, getting xAuth from Twitter, and all other blah blah stuff?<br />
Heck it was easier than even In App Email/SMS! However all these don&#8217;t come for free.</p>
<h1>Drawbacks</h1>
<p>The only biggest drawback I could think of is, your app doesn&#8217;t get any attribution for the tweets sent. Twitter.com or any client shows that the tweet was sent &#8220;via iOS&#8221; instead of your app name and I don&#8217;t see a way to set this up in the Framework.<br />
This shouldn&#8217;t be a problem since Twitter is slowly &#8220;abandoning&#8221; the via text (at least on the stream page now). So what? Let&#8217;s start using Apple&#8217;s Twitter.Framework from now on, instead of the third party frameworks.</p>
<h1>Source Code</h1>
<p>The source code for this tutorial is available here.<br />
<a title="TwitterTest.zip" href="http://blog.mugunthkumar.com/wp-content/uploads/TwitterTest.zip">TwitterTest.zip</a></p>
<p>&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1214_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1214?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1214_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1214&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-sending-in-app-tweets%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="iOS+Tutorial%3A+Sending+In+App+Tweets" data-count="horizontal" data-text="iOS Tutorial: Sending In App Tweets" data-url="http://blog.mugunthkumar.com/coding/ios-tutorial-sending-in-app-tweets/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-sending-in-app-tweets%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fios-tutorial-sending-in-app-tweets%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/ios-tutorial-sending-in-app-tweets/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Easy Debugging with ASIHTTPRequest</title>
		<link>http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/</link>
		<comments>http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 11:00:19 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[asihttprequest]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[objective c]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1266</guid>
		<description><![CDATA[Just wrote this quick and dirty method that dumps a ASIHTTPReqeust on console as a curl command. You can add it to your project as a category extension on ASIHTTPRequest or on a subclass (if you have one). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/' rel='bookmark' title='Easy Debugging with NSMutableURLRequest'>Easy Debugging with NSMutableURLRequest</a> <small>This post is a sequel to one of my previous...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>Just wrote this quick and dirty method that dumps a ASIHTTPReqeust on console as a curl command. You can add it to your project as a category extension on ASIHTTPRequest or on a subclass (if you have one).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> description
<span style="color: #002200;">&#123;</span>
    __block <span style="color: #400080;">NSMutableString</span> <span style="color: #002200;">*</span>displayString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\n</span>Request<span style="color: #2400d9;">\n</span>-------<span style="color: #2400d9;">\n</span>curl -X %@&quot;</span>, self.requestMethod<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self requestHeaders<span style="color: #002200;">&#93;</span> enumerateKeysAndObjectsUsingBlock<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> key, <span style="color: #a61390;">id</span> val, <span style="color: #a61390;">BOOL</span> <span style="color: #002200;">*</span>stop<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #002200;">&#91;</span>displayString appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; -H <span style="color: #2400d9;">\&quot;</span>%@: %@<span style="color: #2400d9;">\&quot;</span>&quot;</span>, key, val<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>displayString appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; <span style="color: #2400d9;">\&quot;</span>%@<span style="color: #2400d9;">\&quot;</span>&quot;</span>,  <span style="color: #002200;">&#91;</span>self.url absoluteString<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self.requestMethod isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;POST&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>bodyString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithData<span style="color: #002200;">:</span>self.postBody 
                                                      encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>displayString appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; -d <span style="color: #2400d9;">\&quot;</span>%@<span style="color: #2400d9;">\&quot;</span>&quot;</span>, bodyString<span style="color: #002200;">&#93;</span>;        
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>self.responseString<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>displayString appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\n</span>--------<span style="color: #2400d9;">\n</span>Response<span style="color: #2400d9;">\n</span>--------<span style="color: #2400d9;">\n</span>%@<span style="color: #2400d9;">\n</span>&quot;</span>, self.responseString<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> displayString;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1266_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1266?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1266_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1266&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-asihttprequest%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="Easy+Debugging+with+ASIHTTPRequest" data-count="horizontal" data-text="Easy Debugging with ASIHTTPRequest" data-url="http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-asihttprequest%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Feasy-debugging-with-asihttprequest%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/easy-debugging-with-nsmutableurlrequest/' rel='bookmark' title='Easy Debugging with NSMutableURLRequest'>Easy Debugging with NSMutableURLRequest</a> <small>This post is a sequel to one of my previous...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/easy-debugging-with-asihttprequest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</title>
		<link>http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/</link>
		<comments>http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 14:31:10 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[in-app purchases]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ios5]]></category>
		<category><![CDATA[mkstorekit]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1248</guid>
		<description><![CDATA[When using MKStoreKit or any other equivalent framework or regular In App Purchases&#8217; StoreKit.framework, If you are getting a problem like this, Cannot connect to iTunes Store Code: Error code: 0 &#160; Error code 0 is SKErrorUnknown. It probably means connection couldn&#8217;t be established from your device to Apple. The number one reason for this [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/' rel='bookmark' title='MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions'>MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions</a> <small>MKStoreKit started off in a pet project a couple of...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/' rel='bookmark' title='iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code'>iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code</a> <small>Just wrote this class, MKiCloudSync (100 lines of code) that...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/ios-code-tweetbot-like-alertpanels/' rel='bookmark' title='iOS Code: TweetBot like AlertPanels'>iOS Code: TweetBot like AlertPanels</a> <small>TweetBot is sexy, no one can deny it. One of...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>When using <a href="http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/">MKStoreKit</a> or any other equivalent framework or regular In App Purchases&#8217; StoreKit.framework, If you are getting a problem like this,</p>
<blockquote><p>Cannot connect to iTunes Store Code: Error code: 0</p></blockquote>
<p>&nbsp;</p>
<p>Error code 0 is SKErrorUnknown. It probably means connection couldn&#8217;t be established from your device to Apple.</p>
<p>The number one reason for this is, you are using a jailbroken iPad that updated the hosts file to block traffic to <strong>gs.apple.com</strong></p>
<p>The second reason which I found today is that you are making the product purchase call on a delegate callback instead of the main thread.</p>
<p>A common example of this is showing the list of products on a UITableView and making the purchase on the UITableViewDelegate. Or showing an additional UIAlertView prompt and making the real purchase on the delegate call back.</p>
<p>StoreKit.framework internally using NSURLConnection and to quote from <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html">Apple Documentation</a></p>
<blockquote><p>By default, for the connection to work correctly, the calling thread’s run loop must be operating in the default run loop mode. See <code><a href="http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLConnection/scheduleInRunLoop:forMode:">scheduleInRunLoop:forMode:</a></code> to change the run loop and mode.</p></blockquote>
<p>You don&#8217;t have control over StoreKit code to change the run loop. As such, you should ensure that, calls to add your product to the queue are done on the main thread.</p>
<p>I&#8217;ll fix this in <a href="https://github.com/MugunthKumar/MKStoreKit">MKStoreKit</a> and commit it to Github. Watch the repo or this blog post for updates.</p>
<p>&#8211;</p>
<p>Mugunth</p>
<p><map name='google_ad_map_1248_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1248?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1248_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1248&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fin-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="In+App+Purchases%3A+Troubleshooting+Code%3D0+%26%238220%3BCannot+connect+to+iTunes+Store%26%238221%3B+%28SKErrorUnknown%29" data-count="horizontal" data-text="In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)" data-url="http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fin-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fin-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/' rel='bookmark' title='MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions'>MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions</a> <small>MKStoreKit started off in a pet project a couple of...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/ios-code-mkicloudsync-sync-your-nsuserdefaults-to-icloud-with-a-single-line-of-code/' rel='bookmark' title='iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code'>iOS Code: MKiCloudSync &#8211; Sync your NSUserDefaults to iCloud with a single line of code</a> <small>Just wrote this class, MKiCloudSync (100 lines of code) that...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/ios-code-tweetbot-like-alertpanels/' rel='bookmark' title='iOS Code: TweetBot like AlertPanels'>iOS Code: TweetBot like AlertPanels</a> <small>TweetBot is sexy, no one can deny it. One of...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using MKStoreKit in your apps</title>
		<link>http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/</link>
		<comments>http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 02:32:11 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[in-app purchases]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mkstorekit]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1210</guid>
		<description><![CDATA[MKStoreKit, as you probably know is a framework for implementing In App Purchases in your app. It supports virtually every feature you could tell and every business model you could (or even Lodsys) ever think of. It supports, Auto-renewable subscriptions, Consumables, non-renewable subscriptions, and good old non-consumables and a whole lot others. The biggest gripe [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/' rel='bookmark' title='MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions'>MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions</a> <small>MKStoreKit started off in a pet project a couple of...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>MKStoreKit, as you probably know is a framework for implementing In App Purchases in your app. It supports virtually every feature you could tell and every business model you could (or even Lodsys) ever think of. It supports, Auto-renewable subscriptions, Consumables, non-renewable subscriptions, and good old non-consumables and a whole lot others.</p>
<p>The biggest gripe among the developer community is that there is no easy to use, step by step guide on how to use it. There are reasons why I couldn&#8217;t publish one.</p>
<h2>Why no demo?</h2>
<p>First and foremost, a working demonstration app implementing MKStoreKit requires an app to be setup on AppStore and this app cannot obviously be published. Conversely, I cannot open source an app that makes money for me through In App Purchases.</p>
<p>If you have an App on iTunes Connect without publishing it, Apple will send you a polite email after 2 or 3 months asking you to publish. Failing which, they remove it for you and will no longer allow you to create an App by the same name. Deleting the app obviously removes associated In App Purchases and the demonstration code will no longer work. It simply doesn&#8217;t make sense to play cat and mouse with Apple and create dummy apps for a demonstration software.</p>
<h2> Design of MKStoreKit </h2>
<p>However, MKStoreKit has been designed keeping this in mind. The whole integration shouldn&#8217;t take more than an hour or so. Implementing the MKStoreKit into your app is as simple as 10 or 15 lines of code.</p>
<p><b>Step 1: Initialization</b> The first step is the initialize it in the AppDelegate using the code,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>MKStoreManager sharedManager<span style="color: #002200;">&#93;</span>;</pre></div></div>

<p><b>Step 2: The Plist magic </b> The second step is to set up your configurations in the plist file, which I think is quite obvious. There are three keys in the plist, one containing an array of non-consumables, one containing an array of consumables and another an array of auto-renewable subscriptions.</p>
<p><b>Step 3: Configuring for Non consumables</b> Non-consumables need no extra configuration. Just enter the list of product ids in the plist file.</p>
<p><b>Step 4: Configuring for consumables </b> For Consumables, you need to tell MKStoreKit, which product it belongs to and the quantity it adds.<br />
For example, com.mycompany.myapp.eggbasket1 = 10 eggs, and com.mycompany.myapp.eggbasket2 = 100 eggs, you need to tell MKStoreKit that both these are the same product &#8220;Egg&#8221; and they add 10 and 100 eggs respectively.</p>
<p>This is precisely what the keys <strong>Count</strong> and <strong>Name</strong> stands for.</p>
<p><b>Step 5: (Auto-renewable subscriptions)</b> For auto-renewable subscriptions, you need to tell the subscription length. MKStoreKit automatically keeps track of subscription expiry and notifies you through NSNotificationCenter if they expire. Since, Apple doesn&#8217;t keep track of subscription length, it&#8217;s your responsibility (which MKStoreKit takes care of) as a developer to remember those subscription length somewhere in your app. </p>
<p><b>Step 6: (Shared Secret) </b> If you use auto-renewable subscriptions, you need to enter set your shared secret. You should do this in MKStoreKitConfigs.h. If you don&#8217;t do this step, MKStoreKit cannot notify you of subscription expiry. Shared Secret is used for subscription verification and it&#8217;s compulsory to set this if you use auto-renewable subscriptions.</p>
<p><b>Step 7: The real purchase</b><br />
The real purchase code is a one liner.</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MKStoreManager sharedManager<span style="color: #002200;">&#93;</span> buyFeature<span style="color: #002200;">:</span>&lt;strong&gt;<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;com.mycompany.myapp.feature1&quot;</span>&lt;<span style="color: #002200;">/</span>strong&gt; 
                                    onComplete<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span> purchasedFeature<span style="color: #002200;">&#41;</span>
     <span style="color: #002200;">&#123;</span>
         NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Purchased: %@&quot;</span>, purchasedFeature<span style="color: #002200;">&#41;</span>;
		<span style="color: #11740a; font-style: italic;">// provide your product to the user here.</span>
		<span style="color: #11740a; font-style: italic;">// if it's a subscription, allow user to use now.</span>
		<span style="color: #11740a; font-style: italic;">// remembering this purchase is taken care of by MKStoreKit.</span>
     <span style="color: #002200;">&#125;</span>
                                   onCancelled<span style="color: #002200;">:^</span>
     <span style="color: #002200;">&#123;</span>
         <span style="color: #11740a; font-style: italic;">// User cancels the transaction, you can log this using any analytics software like Flurry.</span>
     <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>Everything happens behind the scenes, automatically. For every kind of product, whether it&#8217;s a consumable or non-consumable, this code is same.</p>
<p><b>Step 8: Expiry notifications for auto-renewable subscriptions</b> Subscribing to subscriptions revoked notifications (only for auto-renewable subscriptions).</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">	<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNotificationCenter</span> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self 
selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span> <span style="color: #002200;">&#40;</span>subscriptionExpired<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> 
name<span style="color: #002200;">:</span> kSubscriptionsInvalidNotification 
object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>It&#8217;s the configuration part that&#8217;s hard. So, as I promised that was under 10 lines right? One line in your AppDelegate, 4 or 5 lines in your Store ViewController and 2 lines to listen for subscription expiry notification. That wasn&#8217;t hard, was it?</p>
<h2>Going forward</h2>
<h3> Lion </h3>
<p>MKStoreKit will soon be released with full support for Lion<br />
Currently, I think it should automatically work, though I haven&#8217;t tested it. If you are using it, do let me know.</p>
<h3> iCloud </h3>
<p> Adding iCloud integration. With iCloud, your purchases will be remembered on iCloud rather than Keychain, which means, you don&#8217;t need to restore transactions on every device. iCloud will do it for you automatically.</p>
<p>The code for this is ready, but the NDA prevents me to push it to Github. Wait till Sep 5th (hopefully)</p>
<p>If you have any other feature requests, or want me to look at your changes, do send me a pull request for the code on Github<br />
<a href="http://github.com/mugunthkumar/MKStoreKit">http://github.com/mugunthkumar/MKStoreKit</a></p>
<p>Hope MKStoreKit helps you and your business. Do consider a paypal donation to mugunth.kumar@gmail.com.</p>
<p>Thanks,<br />
&#8211;<br />
Mugunth</p>
<p><map name='google_ad_map_1210_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1210?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1210_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1210&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fusing-mkstorekit-in-your-apps%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="Using+MKStoreKit+in+your+apps" data-count="horizontal" data-text="Using MKStoreKit in your apps" data-url="http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fusing-mkstorekit-in-your-apps%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fusing-mkstorekit-in-your-apps%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/' rel='bookmark' title='MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions'>MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions</a> <small>MKStoreKit started off in a pet project a couple of...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions</title>
		<link>http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/</link>
		<comments>http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/#comments</comments>
		<pubDate>Fri, 08 Jul 2011 06:15:52 +0000</pubDate>
		<dc:creator>Mugunth Kumar</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[iap]]></category>
		<category><![CDATA[in-app purchases]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ios 4]]></category>
		<category><![CDATA[ios 5]]></category>
		<category><![CDATA[lion]]></category>
		<category><![CDATA[mkstorekit]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.mugunthkumar.com/?p=1180</guid>
		<description><![CDATA[MKStoreKit started off in a pet project a couple of years ago and I wrote the first version in 2009. Since then, it has seen tremendous adoption rates that, it has been the &#8220;go-to&#8221; framework for implementing In-App purchases in any iOS app today. On iOS 4.3, Apple added a new type of subscription framework [...]
Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/' rel='bookmark' title='Using MKStoreKit in your apps'>Using MKStoreKit in your apps</a> <small>MKStoreKit, as you probably know is a framework for implementing...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
<li><a href='http://blog.mugunthkumar.com/articles/migrating-your-code-to-objective-c-arc/' rel='bookmark' title='Migrating your code to Objective-C ARC'>Migrating your code to Objective-C ARC</a> <small>Recently, Apple introduced several new developer stuff including Xcode 4,...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p>MKStoreKit started off in a pet project a couple of years ago and I wrote the first version in 2009.<br />
Since then, it has seen tremendous adoption rates that, it has been the &#8220;go-to&#8221; framework for implementing In-App purchases in any iOS app today.</p>
<p>On iOS 4.3, Apple added a new type of subscription framework called, auto-renewable subscriptions.</p>
<p>Today, I&#8217;m adding this support to MKStoreKit along with several new features. If you have been following me on <a href="http://twitter.com/mugunthkumar">Twitter (@mugunthkumar)</a> or on <a href="http://github.com/mugunthkumar">Github</a>, you would have gotten the code a week ago.<br />
Now that, I&#8217;m done with my testing it&#8217;s finally ready for some real-world adoption in your projects.</p>
<h2>What&#8217;s New</h2>
<ol>
<li> The main feature includes support for Auto-renewable subscriptions.</li>
<li> The second important change is to move configuration related changes to a separate file,

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">MKStoreKitConfigs.h and
MKStoreKitConfigs.plist</pre></div></div>

<p>The plist contains a list of products you support and MKStoreKit automatically reads this and creates StoreKit requests on your behalf. This feature was partly inspired by a issue raised <a href="https://github.com/MugunthKumar/MKStoreKit/issues/6">here</a> by a contributor, <a href="https://github.com/dfabulich">dfabulich</a>. But I didn&#8217;t like adding a datasource to MKStoreKit for various reasons. I think this method is cleaner than that. MKStoreKit now behaves like a standalone drop-in package.</li>
<li> MKStoreKitDelegate removed in favour of Blocks</li>
<li> Keychain support using SFHFKeychainUtils<br />
<h2>How to use</h2>
<p>The most important change to MKStoreKit is the use of a plist file instead of Macro strings for your product ids.<br />
The following screenshot shows the plist file organization.<br />
<img title="MKStoreKitConfigs.plist.png" src="http://blog.mugunthkumar.com/wp-content/uploads/MKStoreKitConfigs.plist_.png" border="0" alt="MKStoreKitConfigs.plist" width="600" height="181" /><br />
There are three main sections, Consumables, Non-consumables and Subscriptions. You specify your product inside each category based on how you added them on iTunes connect.<br />
After that, MKStoreKit does the rest.<br />
Non-consumable and Subscriptions are straight forward. I think I might need to explain a bit about Consumable support.</p>
<p>Every consumable entry in this plist needs to be a dictionary with &#8220;Count&#8221; and &#8220;Name&#8221; defined. Imagine that your app is a fish tank app with eggs, plants and fishes as consumables. Fishes are going to be sold on a per-fish basis. However, you might be interested in selling eggs as discounted basket. To allow this business model, I&#8217;ve added a new entry called unique name to every consumable.</p>
<p>If your products, for example,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">com.myfishapp.eggbasket50 <span style="color: #002200;">=</span> $2
com.myfishapp.eggbasket500 <span style="color: #002200;">=</span> $15
com.myfishapp.eggbasket5000 <span style="color: #002200;">=</span> $ <span style="color: #2400d9;">125</span></pre></div></div>

<p>are in fact same in your business (in this case they are all eggs, just that the count is different and subsidized for bulk purchases), you can define them on plist as individual consumable mapping to the same name.<br />
MKStoreKit will then treat all these products as same when remembering purchases.</p>
<p>So instead of you remember how many fish eggs this person has purchased, you can leave that task to MKStoreKit. You get a nice wrapper around them and call these methods on MKStoreKit</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> canConsumeProduct<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> productName quantity<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> quantity;</pre></div></div>

<p>to check for product availability and</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> consumeProduct<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> productName quantity<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> quantity;</pre></div></div>

<p>to notify MKStoreKit to deduct the consumable&#8217;s balance.</p>
<p>This support was originally added to MKStoreKit 3.5, but it didn&#8217;t support product bundles. MKStoreKit v4 adds support for this.</p>
<h2>Subscriptions expiry notification</h2>
<p>MKStoreKit automatically posts notifications when your auto-renewable subscriptions are renewed or failed validation (expired). Observe the following notifications,</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">kSubscriptionsPurchasedNotification
kSubscriptionsInvalidNotification</pre></div></div>

<p>on your view controller or AppDelegate and take corresponding actions.</p>
<h2>A note for MKStoreKit 3 users</h2>
<p>MKStoreKit 4 uses keychain to remember purchases. This is partly to support In-App purchases on the upcoming operating system, OS X Lion. On iOS, all apps are sand-boxed and outside access to NSUserDefaults is not possible (unless the device is jail-broken). So remembering purchases on NSUserDefaults was *good enough*. On Lion, however, NSUserDefaults file is just another plist that could be edited on any text editor and technically &#8220;buy&#8221; our in-app feature. To circumvent this piracy, MKStoreKit 4 will use keychain instead of NSUserDefaults.<br />
As such if you have any consumables, they will not be automatically migrated to keychain store by MKStoreKit. You should do that part yourself. Non-consumables and Subscriptions doesn&#8217;t have this issue.</p>
<h2>Source Code</h2>
<p>The complete source is available on <a href="http://github.com/MugunthKumar/MKStoreKit">Github</a></p>
<h2>Demo Project</h2>
<p>There isn&#8217;t a demo project available because of the nature in which In-App purchases work.<br />
The only way would be to create a dummy project from my iTunes store account and create IAP. But that would add maintenance nightmare for me. However, since MKStoreKit is self-contained, you shouldn&#8217;t normally have trouble integrating it into the product.</p>
<h2>Licensing</h2>
<p>It&#8217;s licensed under Zlib as I feel that&#8217;s the most open license ever.</p>
<h2>A word on third-party components</h2>
<p>MKStoreKit uses the following third-party components.</p>
<ol>
<li><a href="https://github.com/johnezang/JSONKit"> JSONKit </a> by John Engelhart (BSD or Apache Licensed)</li>
<li>NSData base64 encoding additions by <a href="http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html">Matt Gallagher</a> (Zlib license)</li>
<li><a href="https://github.com/ldandersen/scifihifi-iphone">SFHFKeychianUtils</a> by Buzz Andersen</li>
</ol>
<h2>Final words</h2>
<p>I&#8217;m still making some touchups and final set of changes. But I think they will mostly be *cosmetic* (code refactoring). Feel free to pull/fork MKStoreKit and leave your feedback.</p>
<h2>Support me</h2>
<p>Hourly rates of a iPhone developer is <a href="http://stackoverflow.com/questions/209170/how-much-does-it-cost-to-develop-an-iphone-application">skyrocket high</a>. I believe this code would have saved your coding hours by at least a day. You can consider supporting further development by funding me through <a href="https://www.paypal.com">PayPal</a>.  My PayPal email is mugunth.kumar@gmail.com<br />
&#8211;<br />
Mugunth</li>
</ol>
<p><map name='google_ad_map_1180_8b86e81420c6776e'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/1180?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_1180_8b86e81420c6776e' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=1180&amp;url= http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fmkstorekit-4-0-supporting-auto-renewable-subscriptions%2F' /></p><p><a href ="http://twitter.com/mugunthkumar">Follow me </a> on Twitter</p><p>&copy;2012 <a href="http://blog.mugunthkumar.com">MKBlog</a>. All Rights Reserved.</p>.<h4 id="tweetandlike-heading"></h4><ul id="tweetandlike-buttons"><li><a href="http://twitter.com/share" data-title="MKStoreKit+4.0+%26%238211%3B+Supporting+Auto+Renewable+Subscriptions" data-count="horizontal" data-text="MKStoreKit 4.0 &#8211; Supporting Auto Renewable Subscriptions" data-url="http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/" data-lang="eng" data-via="@mugunthkumar" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><g:plusone size= "medium" href= "http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fmkstorekit-4-0-supporting-auto-renewable-subscriptions%2F"></g:plusone></li><li><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.mugunthkumar.com%2Fcoding%2Fmkstorekit-4-0-supporting-auto-renewable-subscriptions%2F&layout=button_count&show_faces=true&action=like&font=segoe ui&colorscheme=light&width=350&scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:350px; height:25px;" allowTransparency="true" ></iframe></li></ul>
<p>Related posts:<ol>
<li><a href='http://blog.mugunthkumar.com/coding/using-mkstorekit-in-your-apps/' rel='bookmark' title='Using MKStoreKit in your apps'>Using MKStoreKit in your apps</a> <small>MKStoreKit, as you probably know is a framework for implementing...</small></li>
<li><a href='http://blog.mugunthkumar.com/coding/in-app-purchases-troubleshooting-code0-cannot-connect-to-itunes-store-skerrorunknown/' rel='bookmark' title='In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)'>In App Purchases: Troubleshooting Code=0 &#8220;Cannot connect to iTunes Store&#8221; (SKErrorUnknown)</a> <small>When using MKStoreKit or any other equivalent framework or regular...</small></li>
<li><a href='http://blog.mugunthkumar.com/articles/migrating-your-code-to-objective-c-arc/' rel='bookmark' title='Migrating your code to Objective-C ARC'>Migrating your code to Objective-C ARC</a> <small>Recently, Apple introduced several new developer stuff including Xcode 4,...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/feed/</wfw:commentRss>
		<slash:comments>135</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced

Served from: blog.mugunthkumar.com @ 2012-02-04 14:16:13 -->
