Last Updated: February 25, 2016
·
957
· widescape

Load JSON without AFNetworking

If your app only needs to load some public JSON files, AFNetworking with CocoaPods is not the nimble solution you're looking for (it adds about 600KB to your compiled app). So, here is a minimal service to help you out:

Shortcut to the Gist: https://gist.github.com/widescape/10466762

Use JSONFromConnection

JSONFromConnection is a combination of NSURLConnection sendAsynchronousRequest and NSJSONSerialization JSONObjectWithData that will do the magic for you while responding with either your perfect data object – or an error message. Just create a NSURLRequest and pass it to JSONFromConnection sendAsynchronousRequest along with a completion block.

// YourController.m
- (void)fetchData
{
  NSString *urlAsString = [NSString stringWithFormat:@"https://api.example.com/%@/%@", apiKey, yourQuery];
  NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlAsString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20];

  __weak UIViewController *weakSelf = self;
  [JSONFromConnection sendAsynchronousRequest:request completeWith:^(id dataFromJSON, NSError *connectionOrJSONError) {
    if (connectionOrJSONError) {
      // Handle the error
      weakSelf.…
    }
    else {
      // Do something with dataFromJSON (NSMutableData)
      weakSelf.…
    }
    [weakSelf broadcastWeatherDataFor:index onQueriedLocation:queriedLocation];
  }];
}

Note: The weakSelf reference helps to avoid problems when your controller was deallocated already when the block is executed.

Setup JSONFromConnection

Just copy the following 2 files into your project. First JSONFromConnection.h …

// JSONFromConnection.h
#import <Foundation/Foundation.h>

@interface JSONFromConnection : NSObject

+ (void)sendAsynchronousRequest:(NSURLRequest*)request completeWith:(void (^)(id dataFromJSON, NSError *connectionOrJSONError))complete;

@end

… and JSONFromConnection.m.

// JSONFromConnection.m
#import "JSONFromConnection.h"

@implementation JSONFromConnection

+ (void)sendAsynchronousRequest:(NSURLRequest*)request completeWith:(void (^)(id dataFromJSON, NSError *connectionOrJSONError))complete {
  [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    if (connectionError) {
      complete(nil, connectionError);
    }
    else {
      NSError *jsonError = nil;
      NSMutableData *unserializedData = [NSJSONSerialization JSONObjectWithData: data options:NSJSONReadingMutableContainers error:&jsonError];
      if (jsonError) {
        complete(data, jsonError);
      }
      else {
        complete(unserializedData, nil);
      }
    }
  }];
}

@end

Tip: Always enable caching

In the example above you'll notice that the request is created using the cachePolicy NSURLRequestUseProtocolCachePolicy that will make use of your apps shared cache. So make sure you set it up:

// AppDelegate.m
#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Setup URL Caching (always a good idea)
  NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                       diskCapacity:20 * 1024 * 1024
                                                           diskPath:nil];
  [NSURLCache setSharedURLCache:URLCache];

  …
  return YES;
}