iOS

Build your own iOS Flickr App: Part 1

Create a simple app that connects to Flickr, sends a request, parses the results, and displays them into a table view.

I am going to assume you all know Flickr. In this tutorial we will show you how to create a simple app that connects to Flickr, sends a request, parses the results, and displays them into a table view. The table view you should be quite familiar with. The Flickr connection itself will be a little bit new, however you will notice that it is very similar to our Twitter app. Finally, we will toy with the app to make it load photos in a non-obstructive way.

The sketch for this app would be simple: A single window that contains a table view.

Steps

Let's review the steps:

  1. Create the app mold
  2. Connect to Flickr
  3. Fetch and Parse the data
  4. Populate the table view
  5. Tinker!

Okay, let's start by creating an Empty Application and call it TRFlickApp. Your app simply contains an AppDelegate. From this AppDelegate we will instantiate a UITableViewController which will display our final data. So go ahead and create a new UITableViewController Class file and name it MyTableViewController.

Aside from the AppDelegate and the UITVC, you will need a Flickr app and a JSON folder to parse json results from web responses. The Flickr app is easy enough to create. Simply go to flickr.com and login with your account or else create a new one. I'll make your life easier and suggest you simply follow this link: http://www.flickr.com/services/apps/create/

You will basically need to Request an API Key. Give your app a title if you wish. The important resource here is the API Key. This is what Flickr.com API will use to authenticate your iOS app in order to access Flickr.com.

Now on to the JSON parser! We will be using Stig Brautaset's JSON parser. It's located at Github and you just need the Classes folder, which contains the SBJSON files in it. So add this to your project.

Now that we have all four resources, let's get to work.

Code

Forward declare your MyTableViewController in your AppDelegate.h, create an ivar for it and make it a property:

@class MyTableViewController;
MyTableViewController *myTableViewController;
@property (nonatomic, retain) IBOutlet UIWindow *window;

The three lines above accomplish this task. You already know where they should go inside your AppDelegate. As for the AppDelegate.m file, import the MyTableViewController, synthesize the property and instantiate/load the vc in the appDidFinishLaunching method.

#import "MyTableViewController.h"
@synthesize myTableViewController;
self.myTableViewController = [[MyTableViewController alloc] initWithStyle:UITableViewStylePlain];
 myTableViewController.view.frame = [UIScreen mainScreen].applicationFrame;
[window addSubview:myTableViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];

And don't forget to release the property in your dealloc method, unless you are using ARC. That's it for the AppDelegate.

Moving on to the vc, add two ivars to contain names and photos in MyTableViewController.h:

NSMutableArray *photoNames;
NSMutableArray *photoURLs;

Let's make sure to import the remaining two resources into MyTableViewController.m:

#import "JSON.h"
#import "FlickrAPIKey.h"

Now let's put these resources together. In your vc initializer, init your array ivars:

- (id)initWithStyle:(UITableViewStyle)style
{
 self = [super initWithStyle:style];
 if (self) {
 photoURLs = [[NSMutableArray alloc] init];
 photoNames = [[NSMutableArray alloc] init];
 [self loadFlickrPhotos];
 }
 return self;
}

Since images need to be larger to be appreciated, let's do the user a favor and enlarge the typical cell by doing this in our viewDidLoad:

- (void)viewDidLoad
{
 self.tableView.rowHeight = 95;
}
You require the numberOfRowsInSection method at least, so implement it based on your array count:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
 return [photoNames count];
}

Now let's assume our photo and names array are populated and worry about displaying them in the table view:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell Identifier"] autorelease];
 cell.textLabel.text = [photoNames objectAtIndex:indexPath.row];
 NSData *imageData = [NSData dataWithContentsOfURL:[photoURLs objectAtIndex:indexPath.row]];
 cell.imageView.image = [UIImage imageWithData:imageData];
 return cell;
}

Ok, let's review. If our photos and names arrays were populated, we would extract the value in the names array and place it in the cell.textLabel.text. We would do something similar with the images. We would extract them into an NSData object and put it into the cell.imageView.image.

Populate the arrays

Now that we have the display part out of the way, let's focus on actually populating those arrays correctly. For that, let's turn to our initWithStyle method where we called a [self loadFlickrPhotos]; method. Let's implement that method now.

- (void)loadFlickrPhotos
{
 // 1. Build your Flickr API request w/Flickr API key in FlickrAPIKey.h
 NSString *urlString = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=%@&tags=%@&per_page=10&format=json&nojsoncallback=1", FlickrAPIKey, @"mayan2012"];
 NSURL *url = [NSURL URLWithString:urlString];
 // 2. Get URLResponse string & parse JSON to Foundation objects.
 NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
 NSDictionary *results = [jsonString JSONValue];
 // 3. Pick thru results and build our arrays
 NSArray *photos = [[results objectForKey:@"photos"] objectForKey:@"photo"];
 for (NSDictionary *photo in photos) {
 // 3.a Get title for e/ photo
 NSString *title = [photo objectForKey:@"title"];
 [photoNames addObject:(title.length > 0 ? title : @"Untitled")];
 // 3.b Construct URL for e/ photo.
 NSString *photoURLString = [NSString stringWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_s.jpg", [photo objectForKey:@"farm"], [photo objectForKey:@"server"], [photo objectForKey:@"id"], [photo objectForKey:@"secret"]];
 [photoURLs addObject:[NSURL URLWithString:photoURLString]];
 }
}

Ok let's review this. Notice it is very similar to Twitter's API. You construct a Request object using something to authenticate you (API Key) and something to look for ("mayan2012" string) in our case.

We then create an NSURL out of the string object. We then get the URL response and parse it using JSONValue and put it into an NSDictionary. We then simply loop through the resulting dictionary and retrieve the values we are interested in and put them into their respective array.

Voila! We are done!

Well, except for one more thing. We need to actually tell the app what our API Key is. Create an Objective C header file called FlickrAPIKey.h and put this line into it:

NSString *const FlickrAPIKey = @"YOURAPIKEYVALUE";

Okay, now you can Build & Run your project. You will see the table view populate with names and images related to "mayan2012" Flickr search.

View controllers

This was a pretty simple app but its intent is quite important. If you have been following our iOS Build it Yourself series, this app will reinforce your knowledge about table view controllers, connecting to web services, using JSON to parse results from the web and basic Objective-C coding practices.

Drop us a line if you have any questions so far. We will continue polishing this app in a second part later this month.

Also read:

About

My name is Marcio Valenzuela and I am from Honduras. I have been coding in iOS for 5 years and I previously worked on web applications in ASP and PHP/mySQL. I have a few apps up in the app store and am currently working on a couple of Cocos2d games...

1 comments
Mark W. Kaelin
Mark W. Kaelin

Do you have any questions about the Flickr App so far?

Editor's Picks