<?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>iPhone Programming Tutorials &#187; dsklenar</title>
	<atom:link href="/author/dsklenar/feed/" rel="self" type="application/rss+xml" />
	<link>http://icodeblog.com</link>
	<description>iPhone Programming Tutorials</description>
	<lastBuildDate>Tue, 19 Nov 2013 19:34:46 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.1</generator>
	<item>
		<title>Tutorial: Asynchronous HTTP Client Using NSOperationQueue</title>
		<link>http://icodeblog.com/2012/10/19/tutorial-asynchronous-http-client-using-nsoperationqueue/</link>
		<comments>http://icodeblog.com/2012/10/19/tutorial-asynchronous-http-client-using-nsoperationqueue/#comments</comments>
		<pubDate>Fri, 19 Oct 2012 09:01:12 +0000</pubDate>
		<dc:creator><![CDATA[dsklenar]]></dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Intermediate]]></category>

		<guid isPermaLink="false">http://icodeblog.com/?p=4235</guid>
		<description><![CDATA[Introduction
Recently here at ELC, we’ve been working on an app that requires a lot of server interaction, which has been a learning experience for managing threading, server load and connectivity. In order to keep the app performant and responsive while sending a large number of requests and aggregating a large set of data, our team had to intelligently manage and prioritize network interactions.
This is where <a title="NSOperationQueue documentation" href="http://developer.apple.com/library/ios/#documentation/cocoa/Reference/NSOperationQueue_class/Reference/Reference.html" target="_blank">NSOperationQueue</a> helps out. This class relies heavily on Grand Central Dispatch  ...]]></description>
				<content:encoded><![CDATA[<p><strong>Introduction</strong></p>
<p>Recently here at ELC, we’ve been working on an app that requires a lot of server interaction, which has been a learning experience for managing threading, server load and connectivity. In order to keep the app performant and responsive while sending a large number of requests and aggregating a large set of data, our team had to intelligently manage and prioritize network interactions.</p>
<p>This is where <a title="NSOperationQueue documentation" href="http://developer.apple.com/library/ios/#documentation/cocoa/Reference/NSOperationQueue_class/Reference/Reference.html" target="_blank">NSOperationQueue</a> helps out. This class relies heavily on Grand Central Dispatch (GCD) to execute NSOperations (in this case, HTTP requests and JSON serializations). These operations can be executed in various configurations, including concurrently and asynchronously.</p>
<p>In this tutorial, I’ll show you how to set up a block-based operation queue that takes advantage of NSBlockOperation, a concrete subclass of NSOperation. You can use this server client class to manage all interactions with your external server. To demonstrate this, our sample code will query Twitter for a set of search tags and return the results asynchronously. The sample code is available on <strong><a href="https://github.com/dsklen/QueuedHTTPClientSample" target="_blank">GitHub</a></strong>. Let’s get started.</p>
<p><strong>Server Client Setup<br />
</strong><br />
First, create a MediaServer class with an operation queue property. This server class is a singleton because we want to route all network requests through a single operation queue.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> MediaServer <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>strong<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSOperationQueue</span> <span style="color: #002200;">*</span>operationQueue;
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sharedMediaServer;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Our server singleton is instantiated as follows. Note that using <code>dispatch_once</code> takes advantage of GCD and is recommended by Apple for thread safety.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sharedMediaServer;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">static</span> dispatch_once_t onceToken;
    <span style="color: #a61390;">static</span> <span style="color: #a61390;">id</span> sharedMediaServer <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    dispatch_once<span style="color: #002200;">&#40;</span> <span style="color: #002200;">&amp;</span>amp;onceToken, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
        sharedMediaServer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> sharedMediaServer;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Next, in MediaServer’s init method, initialize the operation queue and set the concurrent operation count. The maxConcurrentOperationCount property can be changed later, too.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#40;</span> self <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>        
        _operationQueue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOperationQueue</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        _operationQueue.maxConcurrentOperationCount <span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><strong>Search Tags Management<br />
</strong><br />
In the project files, you’ll notice SearchTagsViewController. I’ve set this up to handle adding, removing and editing Twitter search tags. You’ll find a pretty straightforward implementation using NSUserDefaults to persist your search tags. The main purpose of this view controller is to prepare a series of server requests.</p>
<p><strong>Server Calls Using NSBlockOperation<br />
</strong><br />
Now, we’re ready to start using our operation queue. For our example, we’ll be searching for tweets containing various keywords, so we only need one fetch method in our server class.</p>
<p>Note: because blocks are a bit syntactically difficult to read, it can be convenient to typedef assign a block’s input and return parameters. This also makes methods much more readable when passing in blocks. For our example, we are expecting an array of tweet objects, and we’ll check for errors in the HTTP request and JSON serialization. In MediaServer.h, add:</p>

<div class="wp_syntax"><table><tr><td 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>FetchBlock<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>items, <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>Now, we’re ready to add our fetch tweets method. This method accepts a search string and a return block (FetchBlock). This method will create an NSBlockOperation instance using blockOperationWithBlock: and dispatch it to the Media Server’s dispatch queue. Within that block, we’ll asynchronously send an NSURLRequest, serialize the response and synchronously return the tweets using our FetchBlock. Let’s take a look at the code.</p>

<div class="wp_syntax"><table><tr><td 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>fetchTweetsForSearch<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>searchString block<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>FetchBlock<span style="color: #002200;">&#41;</span>block;
<span style="color: #002200;">&#123;</span>
    NSBlockOperation <span style="color: #002200;">*</span>operation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSBlockOperation blockOperationWithBlock<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>tweetObjects <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
        <span style="color: #400080;">NSHTTPURLResponse</span> <span style="color: #002200;">*</span>response <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
&nbsp;
        <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>encodedSearchString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>searchString stringWithURLEncoding<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>URLString <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://search.twitter.com/search.json?q=%@&amp;amp;rpp=%i&amp;amp;include_entities=true&amp;amp;result_type=mixed&quot;</span>, encodedSearchString, SEARCH_RESULTS_PER_TAG<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSURLRequest</span> <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURLRequest</span> requestWithURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span>URLString<span style="color: #002200;">&#93;</span> cachePolicy<span style="color: #002200;">:</span>NSURLRequestReloadIgnoringLocalCacheData timeoutInterval<span style="color: #002200;">:</span>DEFAULT_TIMEOUT<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURLConnection</span> sendSynchronousRequest<span style="color: #002200;">:</span>request returningResponse<span style="color: #002200;">:&amp;</span>amp;response error<span style="color: #002200;">:&amp;</span>amp;error<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>JSON <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSJSONSerialization JSONObjectWithData<span style="color: #002200;">:</span>data options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:&amp;</span>amp;error<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>tweets <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>JSON objectForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;results&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Serialize JSON response into lightweight Tweet objects for convenience.</span>
&nbsp;
        <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>tweetDictionary <span style="color: #a61390;">in</span> tweets <span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            Tweet <span style="color: #002200;">*</span>tweet <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>Tweet alloc<span style="color: #002200;">&#93;</span> initWithJSON<span style="color: #002200;">:</span>tweetDictionary<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#91;</span>tweetObjects addObject<span style="color: #002200;">:</span>tweet<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>        
&nbsp;
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Search for '%@' returned %i results.&quot;</span>, searchString, <span style="color: #002200;">&#91;</span>tweetObjects count<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Return to the main queue once the request has been processed.</span>
&nbsp;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOperationQueue</span> mainQueue<span style="color: #002200;">&#93;</span> addOperationWithBlock<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> error <span style="color: #002200;">&#41;</span>
                block<span style="color: #002200;">&#40;</span> <span style="color: #a61390;">nil</span>, error <span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">else</span>
                block<span style="color: #002200;">&#40;</span> tweetObjects, <span style="color: #a61390;">nil</span> <span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Optionally, set the operation priority. This is useful when flooding</span>
    <span style="color: #11740a; font-style: italic;">// the operation queue with different requests.</span>
&nbsp;
    <span style="color: #002200;">&#91;</span>operation setQueuePriority<span style="color: #002200;">:</span>NSOperationQueuePriorityVeryHigh<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self.operationQueue addOperation<span style="color: #002200;">:</span>operation<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><strong>Dispatching Tweet Searches<br />
</strong><br />
Let’s look at how we’ll use this server method. In TweetsViewController’s viewDidLoad: method, we’ll want to loop through our search tags and fetch each set of tweets. Because each operation is dispatched to our operation queue, we don’t have to worry about swamping the server or causing timeouts due to limited network bandwidth. To do so, in viewDidLoad:, add:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="objc" style="font-family:monospace;">MediaServer <span style="color: #002200;">*</span>server <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>MediaServer sharedMediaServer<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>tag <span style="color: #a61390;">in</span> self.tags<span style="color: #002200;">&#41;</span> 
    <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>server fetchTweetsForSearch<span style="color: #002200;">:</span>tag block<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>items, <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;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> items <span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp; error <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span> <span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self.tweets addObjectsFromArray<span style="color: #002200;">:</span>items<span style="color: #002200;">&#93;</span>;
&nbsp;
                <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>sortDescriptorsArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSSortDescriptor</span> sortDescriptorWithKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;createdAtDate&quot;</span> ascending<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>self.tweets sortUsingDescriptors<span style="color: #002200;">:</span>sortDescriptorsArray<span style="color: #002200;">&#93;</span>;
&nbsp;
                <span style="color: #002200;">&#91;</span>self.tableView reloadData<span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>self.activity stopAnimating<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><strong>Canceling Tweet Searches<br />
</strong><br />
In certain cases, you might want to cancel operations in your queue, for example, when the user navigates away from a view displaying content from several server requests. In this example, when the user taps the back ‘Tags’ button, we want to prevent the remaining search requests from going through. This is as easy as:</p>

<div class="wp_syntax"><table><tr><td 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>viewDidDisappear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated;
<span style="color: #002200;">&#123;</span>
    MediaServer <span style="color: #002200;">*</span>server <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>MediaServer sharedMediaServer<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>server operationQueue<span style="color: #002200;">&#93;</span> cancelAllOperations<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Note that this doesn’t immediately remove operations from the queue, instead it notifies the queue to abort the operation as soon as possible. If you need more specific control of which operations to keep running, NSOperationQueue also exposes an operations property to manually cancel specific operations.</p>
<p><strong>Concurrency</strong></p>
<p>The only thing fetchTweetsForSearch:block: does is create an operation and submit it to the queue, so it returns almost immediately. The main benefit of this approach is that all of the work within the block operation occurs on a background queue, leaving the main thread free and ensuring that the UI remains responsive. To confirm this is working properly, you can open up the Time Profiler in Instruments (an extremely useful tool for improving UX) and check which queue the block is executed on.</p>
<p><img alt="Profiled NSOperation" src="/wp-content/uploads/2012/10/NSOperation-Threading-Profiler.png" /></p>
<p>In the profiler, you’ll see that <code>initWithJSON:</code>, <code>JSONObjectWithData:options:error:</code> and sendSynchronousRequest:returningResponse:error: are all executed on a dispatched worker thread, not the main thread. That’s exactly what we want.</p>
<p><strong>Conclusion</strong></p>
<p>There you have it. As a developer, you’ll glean the most benefit from this server paradigm when sending out a large number of URL requests or when your user is on a slow network. If you do encounter situations where your queue is filling up with requests, remember that you can prioritize your operations, e.g.,</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>operation setQueuePriority<span style="color: #002200;">:</span>NSOperationQueuePriorityVeryHigh<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Another benefit of this approach is the ability to return cached data using our FetchBlock, while updating from the server in the background. Look for more on that in a later blog post.</p>
<p>Happy iCoding!</p>
<p><strong><a title="Sample code" href="https://github.com/dsklen/QueuedHTTPClientSample" target="_blank">Source Code &#8211; GitHub</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://icodeblog.com/2012/10/19/tutorial-asynchronous-http-client-using-nsoperationqueue/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
