iOS Development Journal

Tips and Tricks Learned the Hard Way

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.

1
2
3
4
5
6
7
8
9
10
11
NSURL *url = [NSURL urlWithString:@"http://iosdevelopmentjournal.com"];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
                                                     completionHandler:
                          ^(NSData *data, NSURLResponse *response, NSError *error) {
    if (data) {
        // Do stuff with the data
    } else {
        NSLog(@"Failed to fetch %@: %@", url, error);
    }
}];
[task resume];

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.

Verifying UIKit Is Running on the Main Thread

As previously mentioned: to get the UI to update, you need to run your UIKit configuring code on the main thread. Peter Stienberger has posted a great snippet of code that raises an assertion whenever you attempt to access UIKit code from off of the main thread. Simply add the file to your project (and swap out the PSPDFLogError with an NSLog) and build and run. Everytime you call UIKit code off of the main thread, it’ll crash your app. Great for finding bugs.

Alignment Options in Auto Layout

In OS X Lion and iOS 6 Apple added a new way to layout views, Auto Layout. This is a very powerful system that will handle a lot of the work and overhead of arranging your views. A well defined layout can make many headaches disapear entirely. However, it is a bit…quirky…to say the least.1

I recommend that you read the guide to the visual format language before going on.

This post will discuss the various options that you can set in constraintsWithVisualFormat:options:metrics:views:. These options affect how the views described in the format string are to be aligned with each other.

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.

Forcing Things to Run on the Main Thread

The Problem

So Apple recommends that we avoid doing too much work on the main thread. This is great advice, the less time you spend wasting CPU cycles in the main thread, the more responsive your UI will be. In my opinion a well defined iOS application will avoid doing more than update the UI on the main thread.

One prime example I’ve run into was some code that did a synchronous network request. It waited for the network response before returning and someone thought it had to run on the main thread. This resulted in a lock-up during some animations I was working on.

There’s a number of topics1 that I plan to discuss about getting things off of the main thread, but today I’m going to discuss running things on the main thread.