Posts in networking

  • NSURLSession delegateQueue Silently Fails if Passed The Main Queue

    Of important note: If you want your callbacks to come on the main queue, you
    cannot create an NSURLSession with
    sessionWithConfiguration:delegate:delegateQueue: and pass
    [NSOperationQueue mainQueue] as the delegateQueue argument. All requests
    will silently fail, and never return if you do.

    Instead you must continue to us dispatch_async(dispatch_get_main_queue(), ...) or [[NSOperationQueue mainQueue] addOperationWithBlock:...].

  • Asynchronous Networking with NSURLSession

    iOS 7 introduces an entire new networking stack for developers,
    NSURLSession. Generally it makes the common tasks simple, and the hard
    tasks possible. It also drives the new background fetch capabilities as well.

    Like my earlier post, offloading your networking from the main
    thread is a simple way to help keep an app responsive. Doing this with
    NSURLSession is actually quite easy.

    {% highlight objc %}
    NSURL *url = [NSURL urlWithString:@""];
    NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
    ^(NSData *data, NSURLResponse *response, NSError *error) {
    if (data) {
    // Do stuff with the data
    } else {
    NSLog(@"Failed to fetch %@: %@", url, error);
    [task resume];
    {% endhighlight %}

    This will run the networking off of the main thread, and the callback will come from a system network queue. Generally this is what we want. If you want to have control over what queue the callback comes from, or to be able to handle authentication requests, you should create your own NSURLSession and delegate.

  • An Example NSURLConnection Delegate

    In the little analytics I've had to this point, I've discovered that people
    have come here while searching for an example NSURLConnection delegate. So
    we're going to walk through an simple example I've coded up.

    This delegate will fetch a requested URL and make the data available to the
    class. We'll allow for simultaneous connections, and callbacks using blocks.

    Here's the header file

    Here's the implementation file

    What's Going On

    Let's look at the full gist and walk through the code.

    The Public Interface

    There are only two methods and two properties that are public for our delegate.
    One method allows for the canceling of all running NSURLConnections. The other

    {% highlight objc %}

    • (void)fetchURL:(NSURL *)url withCompletion:(ExampleDelegateSuccess)completion failure:(ExampleDelegateFailure)failure;
      {% endhighlight %}

    is used to start a request.

    The properties are simple, and allow a user to tweak NSURLRequest's two primary settings: timeoutInterval and cachePolicy. We'll set sane defaults so no one has to worry about them.

    The Private Interface

    We have two additional properties defined. One is a mutable array where we will store active connections. The other is a NSOperationQueue which is where the delegate callbacks will run.

    A Private Class

    An NSURLConnection doesn't have much data with it. If we only allowed one
    call at a time, we could simply have a single property for the data we
    receive. But since we'll have multiple connections running at once, it is
    impractical to manage them[1] in our delegate class. Instead we create a
    child class of NSURLConnection that will store our two blocks and the
    received data and response. Once a connection is started, it continues to exist
    until it is complete, so this is an easy place to store such information.


    This method is simple. We create an NSURLRequest and then create a
    connection with that. If we can't create a connection, we call the failure
    block with a custom error[2]. Then we assign values to our custom
    properties and start the connection. Once the connection has started we track
    it in our array.

    The Delegate Callbacks (NSURLConnectionDelegate)

    You have to implement two delegate protocols to use NSURLConnection. The
    first NSURLConnectionDelegate only has one required method as of iOS 5.0.


    This is an easy one to handle. We simply call our failure block with the error
    and remove the connection from our tracking array.

    The Delegate Callbacks (NSURLConnectionDataDelegate)

    This delegate has the meat of the callbacks[3]. They handle the responses we receive from the server.


    Apple's documentation informs us that every
    time this method is called we need to zero out the received data. Besides that
    anything we do is up to us. We store the response for use for later, in case of


    This method provides us with the data the server has sent. We go ahead and append it our connection's data.


    When this callback is called, we know the connection is done. We don't know if
    it was successful, but no more callbacks will be called after this. So here we
    investigate the response object to see if the call was a success.

    Since an HTTP response might indicate failure we check to see if the response
    if an NSHTTPURLResponse and see if it has an error status code. If so, we
    call the failure block with an error holding the status code's message.

    If the response wasn't an HTTP response, or didn't have an error, we go ahead
    and call the completion block so the user has the received data.

    1. You might consider managing connections an their associated data with an NSDictionary using the connection as a key. This doesn't work since NSURLConnection's don't implement NSCopying and can't be used as keys in NSDictionary's. A CFDictionary works, but is more work with memory management. And don't even consider using similarly ordered arrays, because then you can't delete items without weird issues. ↩︎

    2. This NSError code is ugly and bad. So bad. You shouldn't use it. ↩︎

    3. So in pre-iOS 5 these were part of NSURLConnectionDelegate protocol but have since moved into their own. Why two protocols? I don't know, but that's how it is. ↩︎

  • Running URL Requests in the Background

    Getting data from the web is a pretty common operation for apps these days.
    Part of the marvel of the iPhone is that you're always connected. Now, often we
    make network requests and don't worry much about them until they're done. What
    you might not know is where the code to handle the request is running. And by
    default that place often ends up being the main thread.

    AFNetworking takes care of this issue for you. If you're curious how it works, or can't use AFNetworking then read on.

    So if you'd like to learn more about how to handle NSURLConnections in the background, read more. If not, just go and use AFNetworking.

    There's 3 basic ways to make requests to get data from a URL. All of them involve the class NSURLConnection.

    1. sendSynchronousRequest:returningResponse:error: - This will block
      until the request is complete. Which means if you run it on the main
      thread, the main thread will be blocked. So basically you probably don't
      want to use this method

    2. sendAsynchronousRequest:queue:completionHandler: - This blocks until
      the request is complete and runs the block completionHandler on queue
      when it's done. So this seems useful, but might cause performance problems
      when you aren't expecting any.

    3. The traditional method, initializing an NSURLConnection, and telling
      it to start. By default this runs on the thread where it is started,
      so usually the main thread.

    So we'll be focusing on the traditional method, since it is the only one that
    really does what we want.

    If you're already just calling start you might wonder why it's not
    causing big issues. Well, if you've programmed the delegate callbacks well,
    then you're only blocking the main thread very briefly. iOS is already pretty
    smart about how often it calls the delegate. Problems might come up if you
    start doing a lot of work from the callback methods, often times in the
    completion callback. You might notice problems like the UI being unresponsive,
    or animation jitter. Thankfully, we can fix this.

    Telling NSURLConnection Where to Work

    There are three ways to tell NSURLConnection where to run its callbacks.

    Calling start from Another Thread

    This sounds easy enough, that's why we have dispatch_async right? Well,
    sadly, no that doesn't work. You see GCD queues are not the same as
    threads[1], and when you call dispatch_async for a particular queue all
    it guarantees is what order it will start relative to other blocks in the
    queue. GCD will create and destroy threads frequently and there's a good
    chance[2] that the thread you call start from will stop existing
    immediately afterwards. This results in the delegate not receiving any

    Instead you need to run start from a specific thread. Doing this is very
    similar to the next method, which provides more flexibility anyhow, and only
    two more lines of code.


    This method which works for all versions of iOS is using
    scheduleInRunLoop:forMode:, which allows you to specify where delegate
    callbacks will occur. It does this by specifying an NSRunLoop.

    NSRunLoops are a representation of a thread. To get an instance of
    NSRunLoop you call the class method
    [NSRunLoop currentRunLoop] which returns a run loop
    for the current thread.

    For this to work you still need to have code run in a specific thread, and then
    call [NSRunLoop currentRunLoop] from within that, and
    pass it to scheduleInRunLoop:forMode:. Because of compatibility, this is
    how AFNetworking manages it's callbacks asynchronously. Here's a bit of the
    from AFNetworking:

    {% highlight objc %}
    self.connection = [[NSURLConnection alloc] initWithRequest:self.request

    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    for (NSString *runLoopMode in self.runLoopModes) {
    [self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
    [self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];

    [self.connection start];
    {% endhighlight %}

    If you look a few lines up from this snippet, you see that calling start on
    an AFURLConnectionOperation runs this bit of code on a separate thread.

    You might ask why even call scheduleInRunLoop:forMode: and not just call
    start. Well if you wanted to configure an NSURLConnection in one
    place, and then call start from somewhere else, even on a different thread,
    this would ensure that it runs on the network thread. So by setting the run
    loop in advance, you can be flexible about when and where you start the

    There's a dirty shortcut
    allowing you to do this when called within a dispatch_async block, but it's
    not a very clean solution, and I don't recommend it.


    The easiest way to manage where your callbacks are run on iOS 5.0 and up is
    setDelegateQueue:. You simply create an NSOperationQueue and assign
    it as the delegateQueue for the NSURLConnection. If I have a connection
    manager class, this takes two bits of code typically:

    {% highlight objc %}

    • (id)init {
      self.queue = [[NSOperationQueue alloc] init];
      {% endhighlight %}

    {% highlight objc%}

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:aURLRequest
    [connection setDelegateQueue:self.queue];
    [connection start];

    {% endhighlight %}

    This removes the need to manage a thread or run loop, and you can focus on the important parts of the code.

    Why Would I Use This Instead of AFNetworking?

    Well, not very often. The big reason for writing your own connection delegate
    is usually to have a single place where response handling code exists, and not
    where the call is. You can do this with AFNetworking, but for simple tasks it
    might make more sense to handle it yourself. The basic NSURLConnection
    delegate code is actually quite simple, so might make more sense than adding
    another framework.

    You also might need to support iOS 4.3, and don't want to use an old release of

    Finally, you might be constrained by the MIT license. Or more likely, your
    lawyers don't want you using it.

    Update 9/15/2013: Fixed references to sendAsynchronousRequest:queue:completionHandler: since it is actually a poor method to use.

    1. Of course the function dispatch_get_main_queue() does ensure things run on the main thread, but that's an exception, not a rule. ↩︎

    2. In my experience a "good chance" is actually "always". Try this and you'll be left wondering why your callbacks never get called. ↩︎