In this episode we take a look at the brand new design of AFNetworking 2.0. We'll convert our TuneStore application to leverage AFNetworking and clean up our View Controller by introducing a new class to handle the network plumbing. We'll also take a look at a handy UIKit category for easily managing an activity indicator's state.
Episode Links AFNetworking 2.0 Migration Guide - Provides a great overview of the new design and how you'll use to migrate your application. AFNetworking 2.0 Docs AFNetworking 2.0 Source Episode Source Code Creating a client to search iTunes #import "AFHTTPSessionManager.h" @interface ITunesClient : AFHTTPSessionManager + (ITunesClient *)sharedClient; - (NSURLSessionDataTask *)searchForTerm:(NSString *)term completion:( void (^)(NSArray *results, NSError *error) )completion; @end #import "ITunesClient.h" @implementation ITunesClient + (ITunesClient *)sharedClient { static ITunesClient *_sharedClient = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURL *baseURL = [NSURL URLWithString:@"https://itunes.apple.com/"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; [config setHTTPAdditionalHeaders:@{ @"User-Agent" : @"TuneStore iOS 1.0"}]; NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:10 * 1024 * 1024 diskCapacity:50 * 1024 * 1024 diskPath:nil]; [config setURLCache:cache]; _sharedClient = [[ITunesClient alloc] initWithBaseURL:baseURL sessionConfiguration:config]; _sharedClient.responseSerializer = [AFJSONResponseSerializer serializer]; }); return _sharedClient; } - (NSURLSessionDataTask *)searchForTerm:(NSString *)term completion:( void (^)(NSArray *results, NSError *error) )completion { NSURLSessionDataTask *task = [self GET:@"/search" parameters:@{ @"country" : @"US", @"term" : term } success:^(NSURLSessionDataTask *task, id responseObject) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response; if (httpResponse.statusCode == 200) { dispatch_async(dispatch_get_main_queue(), ^{ completion(responseObject[@"results"], nil); }); } else { dispatch_async(dispatch_get_main_queue(), ^{ completion(nil, nil); }); NSLog(@"Received: %@", responseObject); NSLog(@"Received HTTP %d", httpResponse.statusCode); } } failure:^(NSURLSessionDataTask *task, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ completion(nil, error); }); }]; return task; } @end Here we return the task so that it can be canceled or so the state property might be observed. Using the client in a view controller NSURLSessionDataTask *task = [[ITunesClient sharedClient] searchForTerm:term completion:^(NSArray *results, NSError *error) { if (results) { self.results = results; [self.tableView reloadData]; } else { NSLog(@"ERROR: %@", error); } }]; Loading images using AFNetworking For each cell we can now use the AFNetworking category method for UIImageView. Just #import "UIImageView+AFNetworking.h" at the top of the file, then in the tableView:cellForRowAtIndexPath: method: cell.artworkImageView.image = nil; [cell.artworkImageView cancelImageRequestOperation]; NSURL *imageURL = [NSURL URLWithString:record[@"artworkUrl100"]]; if (imageURL) { [cell.artworkImageView setImageWithURL:imageURL]; } Easily showing an activity indicator when a task is running Using another handy category method, add #import "UIActivityIndicatorView+AFNetworking.h" at the top of the file, then after making the request, you can use the resulting task... [self.activityIndicator setAnimatingWithStateOfTask:task]; This will show the indicator spinning when the request is running, but when it is paused or canceled the animation is stopped.