Three20 Tutorial for iOS: How To Use the Three20 Photo Viewer

A Three20 tutorial that shows you how to use the open source Three20 library’s photo viewer inside your apps. By Ray Wenderlich.

Leave a rating/review
Save for later
Share

Create a full-featured photo viewer easily!

Create a full-featured photo viewer easily!

It’s a common requirement for apps to display images in a similar manner to the Photos app on the iPhone. One simple way to implement this is by using the TTPhotoViewController from the open source Three20 library.

In this Three20 tutorial, we will cover how you can use Three20 to make a simple app that displays a set of photos just like the Photos app does – complete with flicking between photos, pinching to zoom, captions, and full screen mode.

Best of all, because you’re using Three20, you get a lot of other great features built in such a built-in thumbnail viewer, being able to retrieve higher resolution images over the network, and caching the retrieved images locally!

If you haven’t used Three20 before, you may wish to check out the Introduction to Three20 tutorial first. However, this Three20 tutorial is fairly self-contained, so it isn’t required!

Adding Three20 To Your Project

Create a new project in XCode by going to File\New Project, select Window-based Application, and make sure to choose iPhone for the product. Click Choose, and name the Project “PhotoViewer.”

Next you need to get a copy of the three20 library. The best way to get the latest copy of three20 is to use the source control system “git.” If you do not already have this installed, you can download a Mac installer.

Once you have git installed, follow the excellent instructions on the three20 web page for instructions on how to pull down the latest code and add it to your project.

At the time of writing this post, there’s one additional step you need to take. The three20 projects are currently set to use iOS 3.0 as the Base SDK, but assuming you are using XCode 3.2.3, this SDK is no longer available. Therefore, you need to double click on each of the Three20 XCode projects in your Groups & Files list to open up the project, go to Project\Edit Project Settings in each Three20 project, and set the Base SDK to iPhone Device 4.0.

Once you’ve done that, add the following to the top of PhotoViewerAppDelegate.h: #import “Three20/Three20.h”

Then compile your project – if it works three20 has been successfully integrated and you can move onto the next step!

Creating a TTPhoto Class

To display a photo in the TTPhotoViewController, Three20 needs some information from our app. Specifically, it needs to know the size of the image, a URL for where to find the image, an optional caption for the image, and few other pieces of information.

To give Three20 this information, we need to create a class representing our photos that implements the TTPhoto protocol. The definition for the TTPhoto protocol looks something like this:

@protocol TTPhoto <NSObject, TTURLObject>
@property (nonatomic) CGSize size;
@property (nonatomic, copy) NSString* caption;
- (NSString*)URLForVersion:(TTPhotoVersion)version;
@property (nonatomic, assign) id<TTPhotoSource> photoSource;
@property (nonatomic) NSInteger index;
@end

So we need to make sure our class has properties for the size of the image and any caption we want to display. We need to create a method to return a URL for the image. And we’ll need properties for a photoSource and index, but we’ll talk about what those mean later.

A note about the method to retrieve a URL – note it takes a TTPhotoVersion parameter. This has values such as TTPhotoVersionSmall or TTPhotoVersionLarge, so we can return different URLs for images of different levels of quality. In fact that’s what we’ll do in this Three20 tutorial – we’ll include a couple small but low quality images embedded with the app, and a large but high quality image on a web server.

So let’s create our own class that implements this protocol. Go to File\New File, choose Cocoa Touch Class\Objective-C class, make sure Subclass of NSObject is selected, and click Next. Name the new file Photo.m (and make sure also create Photo.h is selected), and click Finish.

Replace Photo.h with the following:

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

@interface Photo : NSObject <TTPhoto> {
    NSString *_caption;
    NSString *_urlLarge;
    NSString *_urlSmall;
    NSString *_urlThumb;
    id <TTPhotoSource> _photoSource;
    CGSize _size;
    NSInteger _index;
}

@property (nonatomic, copy) NSString *caption;
@property (nonatomic, copy) NSString *urlLarge;
@property (nonatomic, copy) NSString *urlSmall;
@property (nonatomic, copy) NSString *urlThumb;
@property (nonatomic, assign) id <TTPhotoSource> photoSource;
@property (nonatomic) CGSize size;
@property (nonatomic) NSInteger index;

- (id)initWithCaption:(NSString *)caption urlLarge:(NSString *)urlLarge urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb size:(CGSize)size;

@end

So basically we’re just creating a subclass of NSObject, but we implement the TTPhoto protocol. We create some properties for caption, photoSource, size, and index, since they’re required in the TTPhoto protocol, and some instance variables to back them up. We also create some instance variables to hold URLs to the three versions of the images we’re going to use for this Three20 tutorial – a “large” version, a “small” version, and a thumbnail version.

Now move over to Photo.m and replace it with the following:

#import "Photo.h"

@implementation Photo
@synthesize caption = _caption;
@synthesize urlLarge = _urlLarge;
@synthesize urlSmall = _urlSmall;
@synthesize urlThumb = _urlThumb;
@synthesize photoSource = _photoSource;
@synthesize size = _size;
@synthesize index = _index;

- (id)initWithCaption:(NSString *)caption urlLarge:(NSString *)urlLarge urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb size:(CGSize)size {
    if ((self = [super init])) {
        self.caption = caption;
        self.urlLarge = urlLarge;
        self.urlSmall = urlSmall;
        self.urlThumb = urlThumb;
        self.size = size;
        self.index = NSIntegerMax;
        self.photoSource = nil;
    }
    return self;
}

- (void) dealloc {
    self.caption = nil;
    self.urlLarge = nil;
    self.urlSmall = nil;
    self.urlThumb = nil;    
    [super dealloc];
}

#pragma mark TTPhoto

- (NSString*)URLForVersion:(TTPhotoVersion)version {
    switch (version) {
        case TTPhotoVersionLarge:
            return _urlLarge;
        case TTPhotoVersionMedium:
            return _urlLarge;
        case TTPhotoVersionSmall:
            return _urlSmall;
        case TTPhotoVersionThumbnail:
            return _urlThumb;
        default:
            return nil;
    }
}

@end

We create a constructor for our Photo that we’ll use later, initializing everything to what’s passed in. Note we just initialize the index and photoSource to dummy values for now – they will be updated later after the constructor is called.

The only method of real interest in this class is URLForVersion: here we examine the version passed in, and return the appropriate URL based on the version. Note we are not including a “medium quality” image in this Three20 tutorial, so we just return the URL for the large image in this case.

By implementing this method, we’ll see that Three20 is smart enough to display the small image first (since it should load more quickly) and then follow up with retrieving the high quality image in the background and replacing the small image when its ready.