iOS Development Journal

Tips and Tricks Learned the Hard Way

Static Libraries Linking to Embedded Frameworks

Are you seeing errors like this:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_TestClass", referenced from:
  objc-class-ref in liblibrary.a(library.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Are you trying to access symbols inside an embedded framework from a static library? dylib and .a mixtures not working?

Well, I was, and here’s what I did.

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.

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];

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.