Clicky

iOS Dev Nugget 228 Recording and Playing Back Network Calls

.

Need to run a code review on your codebase? Hire me

Did you know that since iOS 2, there's a class included in Foundation called NSURLProtocol?

From the docs:

An NSURLProtocol object handles the loading of protocol-specific URL data. The NSURLProtocol class itself is an abstract class that provides the infrastructure for processing URLs with a specific URL scheme. You create subclasses for any custom protocols or URL schemes that your app supports.

Basically, it lets you implement a proxy for URL loading in your app. How does that help?

  1. I like to work offline — without connectivity to focus — sometimes. But most apps need to at least make a network request or two and fetch some data via an API call. You can use NSURLProtocol to do just that.
  2. Alternatively, you might be have automated tests that makes network calls. You'll generally want those to be deterministic and playing back a known, static version using NSURLProtocol is very useful.

There's a library that does just that — VCRURLConnection. From the README, here's how you make a recording:

[VCR start];

NSString *path = @"http://example.com/example";
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

// use either NSURLSession or NSURLConnection
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request];
[task resume];

// NSURLSession makes a real network request and VCRURLConnection
// will record the request/response pair.

// once async request is complete or application is ready to exit:
[VCR save:@"/path/to/cassette.json"]; // copy the output file into your project

You can play it back with:

NSURL *cassetteURL = [NSURL fileURLWithPath:@"/path/to/cassette.json"];
[VCR loadCassetteWithContentsOfURL:cassetteURL];
[VCR start];

// request an HTTP interaction that was recorded to cassette.json
NSString *path = @"http://example.com/example";
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

// use either NSURLSession or NSURLConnection
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request];
[task resume];

// The cassette has a recording for this request, so no network request
// is made. Instead NSURLConnectionDelegate methods are called with the
// previously recorded response.

It's available over Carthage and Cocoapods. Pretty handy isn't it?


Your feedback is valuable: Do you want more nuggets like this?   Yes   or   No

.

.

Like this and want such iOS dev nuggets to be emailed to you, weekly?

Sign Me Up! or follow @iosdevnuggets on Twitter

.

View archives of past issues