Show Menu

Need an iOS Developer?

Submit your 30 day Job Listing for FREE

iOS development tutorial

One of the most common jobs mobile apps perform these days is connecting to an online service and displaying its content to users.

For the purpose of this tutorial we will be interacting with the Dribbble API, since it doesn’t require an API key and is fairly simple to use. Check out the full API documentation for more info.

On the app side we will be using two great open source libraries: AFNetworking for performing HTTP requests and MagicalRecord to ease interaction with CoreData.

Getting Started

To start off we will be creating a new “Empty Application” Xcode project. Name it whatever you want, but be sure to leave “Use Core Data” unchecked

To include MagicalRecord & AFNetworking into our project I recommend using CocoaPods. If you don’t know what CocoaPods is, this site has a great tutorial here.

#Your PodFile:
platform :ios, "7.0"
pod "AFNetworking"
pod "MagicalRecord"

As an alternative you can of course add the libraries manually.

CoreData

Next up we will create the CoreData model, which in our case will consist of a single “DribbbleShot” entity to hold information such as name, player name and image url. Start by creating the data model with New File -> Core Data -> Data Model and name it whatever you want.

Select the created model, add the “DribbbleShot” entity and add the attributes needed:

iOS CoreData Model

To actually interact with the created entity we will create an NSMangedObject subclass, do this by New File -> Core Data -> NSManagedObject Subclass.

Some Glue

To display the data we will be getting from the API we will create UITableViewController wrapped in a UINavigationController as well as a UITableViewCell subclass to display the actual data. Since this setup is so commong and rather simple I won’t explain this here. Check out the example project though for the implementation.

To use MagicalRecord, AFNetworking and our created classes be sure to import them where they are needed

#import "CoreData+MagicalRecord.h"
#import "AFNetworking.h"
#import "UIImageView+AFNetworking.h"
#import "DribbbleShot.h"
#import "TableViewController.h"
#import "ShotCell.h"

The AppDelegate

In our AppDelegate we will need to make a single call to the MagicalRecord to setup CoreData and initialize our views. The application:didFinishLaunchingWithOptions: should look something like this


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//CoreData setup
[MagicalRecord setupAutoMigratingCoreDataStack];

//View setup
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

TableViewController *tableViewController = [TableViewController new];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];

self.window.rootViewController = navController;
[self.window makeKeyAndVisible];

return YES;
}

Piecing It All Together

Our UITableViewController will do all the heavy lifting, for simplicity the example project doesn’t excapulate the data source into an extra class. In a proper project this should be done however.

To interact with the Dribbble API we will be using AFNetworking’s AFHTTPRequestOperationManager. Create an instance variable and instantiate it the the the API base URL, also add a refresh button to trigger loading of new data:


@interface TableViewController ()
{
    AFHTTPRequestOperationManager *_operationManager;
}
@end

@implementation TableViewController
#pragma mark - LifeCycle
- (void)viewDidLoad
{
[super viewDidLoad];
//Initialize AFHTTPRequestOperationManager with Dribbble API base URL
_operationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://api.dribbble.com/"]];
//Refresh button
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshData)];
}

The refresh button calls our refreshData method, this is where all the magic happens


-(void) refreshData
{
//Fetch popular shots from Dribbble API
[_operationManager GET:@"shots/popular" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

//Success
//AFNetworking parses the JSON response, which can now be used like a NSDictionary
id shots = [operation.responseObject objectForKey:@"shots"];

//Loop through shots from API
for (id shot in shots)
{
//Take some values we'll need
NSString *shotId = [[shot objectForKey:@"id"] stringValue];
NSString *shotName = [shot objectForKey:@"title"];
NSString *imageUrl = [shot objectForKey:@"image_teaser_url"];
NSString *playerName = [[shot objectForKey:@"player"] objectForKey:@"name"];

//Check if we already saved this shot...
DribbbleShot *existingEntity = [DribbbleShot MR_findFirstByAttribute:@"shotId" withValue:shotId];

//...if not, create a new entity
if (!existingEntity) 
{
DribbbleShot *shotEntity = [DribbbleShot MR_createEntity];
shotEntity.shotId = shotId;
shotEntity.name = shotName;
shotEntity.playerName = playerName;
shotEntity.imageUrl = imageUrl;
}
}

//Persist created entities to storage
[MagicalRecord saveUsingCurrentThreadContextWithBlock:nil completion:^(BOOL success, NSError *error) {

//Fetch all stored entities & reload tableView
_shotsArray = [DribbbleShot MR_findAll];
[self.tableView reloadData];
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

//Failure
NSLog(@"Failed to fetch shots from Dribbble API!");

} ];
}

Ok, There is a lot going on here. Lets go through it step by step:

We start of by executing a HTTP GET request using the AFHTTPRequestOperationManager. We specify a API extension which in the background is appended to the base url we set earlier. The request operation is either successful or fails. If it fails we will just log an error message to the console.


[_operationManager GET:@"shots/popular" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

//Success

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

//Failure

NSLog(@"Failed to fetch shots from Dribbble API!");

} ];

If the request was successful we will process the data returned. The Dribbble API returns a JSON response which AFNetworking automatically parses into a NSDictionary. We can easily iterate through all the returned Dribbble shots and extract names, image urls etc.


id shots = [operation.responseObject objectForKey:@"shots"];

for (id shot in shots)
{
//Take some values we'll need
NSString *shotId = [[shot objectForKey:@"id"] stringValue];
NSString *shotName = [shot objectForKey:@"title"];
NSString *imageUrl = [shot objectForKey:@"image_teaser_url"];
NSString *playerName = [[shot objectForKey:@"player"] objectForKey:@"name"];
}

This is where CoreData & MagicalRecord come in play. First we check if we havn’t already saved the dribbble shot by comparing the “shotId” attribute.


DribbbleShot *existingEntity = [DribbbleShot MR_findFirstByAttribute:@"shotId" withValue:shotId];

If the shot doesn’t exist we create a new DribbbleShot entity and assign it the shots values:


if (!existingEntity)

{
DribbbleShot *shotEntity = [DribbbleShot MR_createEntity];
shotEntity.shotId = shotId;
shotEntity.name = shotName;
shotEntity.playerName = playerName;
shotEntity.imageUrl = imageUrl;
}

To actually persist the created entities to disk we call the saveUsingCurrentThreadContextWithBlock:completion: on the MagicalRecord helper class. On completion we retrieve all saved entities, add them to an array and reload our UITableView.


[MagicalRecord saveUsingCurrentThreadContextWithBlock:nil completion:^(BOOL success, NSError *error) {

_shotsArray = [DribbbleShot MR_findAll];
[self.tableView reloadData];

}];

Last Touch

All loaded data is now persisted, to display it on launch without having to reload it from the API fetch all DribbbleShot entites on app launch. Add following code at the end of out TableViewController’s viewDidLoad method:


_shotsArray = [DribbbleShot MR_findAll];

[self.tableView reloadData];

Closing Words

This is of course just a very basic example of how to interact with a web API. For larger projects it would make sense to encapsulate all API calls & data processing in an extra class.

If you’d like to learn more about the MagicalRecord framework, I wrote a detailed tutorial on my personal blog.

having issues?

We have a Questions and Answer section where you can ask your iOS Development questions to thousands of iOS Developers.

Ask Question

FREE Download!

Get your FREE Swift 2 Cheat Sheet and quick reference guide PDF download when you sign up to SwiftMonthly


Sharing is caring

If you enjoyed this tutorial, please help us and others by sharing using one of the social media buttons below.


Written by:

Freelance iOS / Web developer & designer for the past 3 years. Created the media and event tracker ComingUp, Spotmote and a few smaller games.

Comments

comments