(转)Three20 开发相册

转至:http://www.wuleilei.com/blog/189

最近几个月一直都在做iPhone项目,至于持续到什么时候还不得而知,所以就只能写iPhone的开发日记了,呵呵,不懂的盆友可以飘过哈~

今天是转载的一片老外用Three20库开发iPhone相册的文章,因为我也使用过此库,感觉很强大,转载过来给需要的童鞋参考。先来张效果图:

Photo applications are very popular with iPhone users. One of the core features of popular photo applications is the Photo Gallery. In this tutorial you will learn to use the Three20 iPhone development Library that is used in the Facebook iPhone application to create a photo gallery to use in your next iPhone application.

Project Overview

Three20 is an iPhone development library. It’s the code that powers the Facebook iPhone app. We will use a small piece of Three20 (TTThumbsViewController) to create a photo gallery similar to the one provided by Apple’s Photos app.

一、 Create a new Xcode project and Add the Three20 Library

1、Open Xcode and create a new iPhone project, selecting “Window Based Application” as the default application type. Name the application “Three20PhotoDemo” or insert a more creative title of your choosing.

2、Clone the Three20 git repository with the following terminal command:

XML/HTML代码
  1. git clone git://github.com/facebook/three20.git 

If you don’t know what Git is or are new to Git, take a look at the Nettuts+ – Easy Version Control with Git Tutorial. You can also download the source files direct from the Three20 GitHub page.

3、Drag the Three20.xcodeproj file (located in “three20/src/Three20″) and drop it onto the root of your Xcode project’s “Groups and Files” sidebar. Make sure that you are grabbing the correct Three20.xcodeproj! The one in “three20/src” is the legacy project which is being phased out. When the dialog appears make sure “Copy items” is unchecked and “Reference Type” is “Relative to Project” before clicking “Add”.

4、Now you need to link the Three20 static library to your project. Click the “Three20.xcodeproj” item that has just been added to the sidebar. Under the “Details” table, you will see a single item: libThree20.a. Check the checkbox on the far right of libThree20.a.

5、Now you need to add Three20 as a dependency of your project, so Xcode compiles it whenever you compile your project. Expand the “Targets” section of the sidebar and double-click your application’s target. Under the “General” tab you will see a “Direct Dependencies” section. Click the “+” button, select “Three20″, and click “Add Target”.

6、Now you need to add the bundle of images and strings to your app. Locate “Three20.bundle” under “Three20/src” and drag and drop it into your project. When the dialog appears make sure “Create Folder References” is selected, “Copy items” is unchecked, and “Reference Type” is “Relative to Project” before clicking “Add”.

7、Now you need to add the Core Animation (QuartzCore) framework to the project. Right click on the “Frameworks” group in your project (or equivalent) and select Add > Existing Frameworks. Then select QuartzCore.framework and add it to the project.

8、Open your “Project Settings” and go to the “Build” tab. Be sure to select the the All Configurations option. Look for “Header Search Paths” and double-click it. Add the relative path from your project’s directory to the “three20/Build/Products/three20″ directory. For example, if your project and the Three20 source are in the same parent, you would enter “../three20/Build/Products/three20″.

9、Also in your “Project Settings”, go to “Other Linker Flags” under the “Linker” section, and add “-ObjC” and “-all_load” to the list of flags.

二、Create Your Interface

Since Three20 does not use Interface Builder, we need to make some final adjustments to the project.
First delete MainWindow.xib
Then open your main.m file and change the last statement to include the name of your Application Delegate.

C++代码
  1. #import     
  2.     
  3. int main(int argc, char *argv[]) {    
  4.          NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
  5.          int retVal = UIApplicationMain(argc, argv, nil, @"Three20PhotoDemoAppDelegate");    
  6.          [pool release];    
  7.          return retVal;    
  8. }  

Lastly, open your Application’s plist file and delete the MainWindow Nib file entry.

 

三、Map URLs to Three20

Three20 uses URLs to navigate from controller to controller. It is modeled after Ruby on Rails routing. We won’t go too deep into everything about URL navigation in Three20. You can read more about it at the URL Navigation section of the Three20 website.
In your Application Delegate implementation file, you will want to import your new Photo Album class.

C++代码
  1. #import "Three20PhotoDemoAppDelegate.h"    
  2. #import "AlbumController.h"    
  3. #import       
  4.     
  5. @implementation Three20PhotoDemoAppDelegate    
  6.     
  7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {        
  8.     
  9.     // Override point for customization after application launch    
  10.     TTNavigator* navigator = [TTNavigator navigator];    
  11.     TTURLMap* map = navigator.URLMap;    
  12.     [map from:@"demo://album" toViewController:  [AlbumController class]];    
  13.     
  14.     [navigator openURLAction:[TTURLAction actionWithURLPath:@"demo://album"]];    
  15.     return YES;    
  16. }    
  17.     
  18. - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {    
  19.     [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:URL.absoluteString]];    
  20.     return YES;    
  21. }    
  22.     
  23. - (void)dealloc {    
  24.     [super dealloc];    
  25. }    
  26. @end  

四、Creating Local Photo Objects

Create the Photo Source;
reate a class by subclassing TTURLRequestModel and implementing the TTPhotoSource delegate.

PhotoSource.h

C++代码
  1. #import       
  2. #import       
  3. typedef enum {    
  4.   PhotoSourceNormal = 0,    
  5.   PhotoSourceDelayed = 1,    
  6.   PhotoSourceVariableCount = 2,    
  7.   PhotoSourceLoadError = 4,    
  8. } PhotoSourceType;    
  9.     
  10. @interface PhotoSource : TTURLRequestModel  {    
  11.   PhotoSourceType _type;    
  12.   NSString* _title;    
  13.   NSMutableArray* _photos;    
  14.   NSArray* _tempPhotos;    
  15.   NSTimer* _fakeLoadTimer;    
  16. }    
  17.     
  18. - (id)initWithType:(PhotoSourceType)type title:(NSString*)title    
  19.       photos:(NSArray*)photos photos2:(NSArray*)photos2;    
  20.     
  21. @end  

PhotoSource.m

C++代码
  1. #import "PhotoSource.h"    
  2.     
  3. @implementation PhotoSource    
  4. @synthesize title = _title;    
  5.     
  6. - (void)fakeLoadReady {    
  7.     _fakeLoadTimer = nil;    
  8.     
  9.     if (_type & PhotoSourceLoadError) {    
  10.     [_delegates makeObjectsPerformSelector: @selector(model:didFailLoadWithError:)    
  11.                                 withObject: self    
  12.                                 withObject: nil];    
  13.     } else {    
  14.     NSMutableArray* newPhotos = [NSMutableArray array];    
  15.     
  16.     for (int i = 0; i < _photos.count; ++i) {    
  17.       id photo = [_photos objectAtIndex:i];    
  18.       if ((NSNull*)photo != [NSNull null]) {    
  19.         [newPhotos addObject:photo];    
  20.       }    
  21.     }    
  22.     
  23.     [newPhotos addObjectsFromArray:_tempPhotos];    
  24.     TT_RELEASE_SAFELY(_tempPhotos);    
  25.     
  26.     [_photos release];    
  27.     _photos = [newPhotos retain];    
  28.     
  29.     for (int i = 0; i < _photos.count; ++i) {    
  30.       id photo = [_photos objectAtIndex:i];    
  31.       if ((NSNull*)photo != [NSNull null]) {    
  32.         photo.photoSource = self;    
  33.         photo.index = i;    
  34.       }    
  35.     }    
  36.     
  37.     [_delegates makeObjectsPerformSelector:@selector(modelDidFinishLoad:) withObject:self];    
  38.   }    
  39. }    
  40.     
  41. - (id)initWithType:(PhotoSourceType)type title:(NSString*)title photos:(NSArray*)photos    
  42.       photos2:(NSArray*)photos2 {    
  43.   if (self = [super init]) {    
  44.     _type = type;    
  45.     _title = [title copy];    
  46.     _photos = photos2 ? [photos mutableCopy] : [[NSMutableArray alloc] init];    
  47.     _tempPhotos = photos2 ? [photos2 retain] : [photos retain];    
  48.     _fakeLoadTimer = nil;    
  49.     
  50.     for (int i = 0; i < _photos.count; ++i) {    
  51.       id photo = [_photos objectAtIndex:i];    
  52.       if ((NSNull*)photo != [NSNull null]) {    
  53.         photo.photoSource = self;    
  54.         photo.index = i;    
  55.       }    
  56.     }    
  57.     
  58.     if (!(_type & PhotoSourceDelayed || photos2)) {    
  59.       [self performSelector:@selector(fakeLoadReady)];    
  60.     }    
  61.   }    
  62.   return self;    
  63. }    
  64.     
  65. - (id)init {    
  66.   return [self initWithType:PhotoSourceNormal title:nil photos:nil photos2:nil];    
  67. }    
  68.     
  69. - (void)dealloc {    
  70.   [_fakeLoadTimer invalidate];    
  71.   TT_RELEASE_SAFELY(_photos);    
  72.   TT_RELEASE_SAFELY(_tempPhotos);    
  73.   TT_RELEASE_SAFELY(_title);    
  74.   [super dealloc];    
  75. }    
  76.     
  77. - (BOOL)isLoading {    
  78.   return !!_fakeLoadTimer;    
  79. }    
  80.     
  81. - (BOOL)isLoaded {    
  82.   return !!_photos;    
  83. }    
  84.     
  85. - (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {    
  86.   if (cachePolicy & TTURLRequestCachePolicyNetwork) {    
  87.     [_delegates makeObjectsPerformSelector:@selector(modelDidStartLoad:) withObject:self];    
  88.     
  89.     TT_RELEASE_SAFELY(_photos);    
  90.     _fakeLoadTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self    
  91.       selector:@selector(fakeLoadReady) userInfo:nil repeats:NO];    
  92.   }    
  93. }    
  94.     
  95. - (void)cancel {    
  96.   [_fakeLoadTimer invalidate];    
  97.   _fakeLoadTimer = nil;    
  98. }    
  99.     
  100. - (NSInteger)numberOfPhotos {    
  101.   if (_tempPhotos) {    
  102.     return _photos.count + (_type & PhotoSourceVariableCount ? 0 : _tempPhotos.count);    
  103.   } else {    
  104.     return _photos.count;    
  105.   }    
  106. }    
  107.     
  108. - (NSInteger)maxPhotoIndex {    
  109.   return _photos.count-1;    
  110. }    
  111.     
  112. - (id)photoAtIndex:(NSInteger)photoIndex {    
  113.   if (photoIndex < _photos.count) {    
  114.     id photo = [_photos objectAtIndex:photoIndex];    
  115.     if (photo == [NSNull null]) {    
  116.       return nil;    
  117.     } else {    
  118.       return photo;    
  119.     }    
  120.   } else {    
  121.     return nil;    
  122.   }    
  123. }    
  124.     
  125. @end  

Create the Photo Object;
Create a class class by subclassing NSObject and implementing the TTPhoto delegate.

Photo.h

C++代码
  1. #import       
  2.     
  3. @interface Photo : NSObject  {    
  4.   id _photoSource;    
  5.   NSString* _thumbURL;    
  6.   NSString* _smallURL;    
  7.   NSString* _URL;    
  8.   CGSize _size;    
  9.   NSInteger _index;    
  10.   NSString* _caption;    
  11. }    
  12.     
  13. - (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size;    
  14.     
  15. - (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size    
  16.       caption:(NSString*)caption;    
  17.     
  18. @end  

Photo.m

C++代码
  1. @implementation Photo    
  2. @synthesize photoSource = _photoSource, size = _size, index = _index, caption = _caption;    
  3.     
  4. - (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size {    
  5.   return [self initWithURL:URL smallURL:smallURL size:size caption:nil];    
  6. }    
  7.     
  8. - (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size    
  9.     caption:(NSString*)caption {    
  10.   if (self = [super init]) {    
  11.     _photoSource = nil;    
  12.     _URL = [URL copy];    
  13.     _smallURL = [smallURL copy];    
  14.     _thumbURL = [smallURL copy];    
  15.     _size = size;    
  16.     _caption = ;    
  17.     _index = NSIntegerMax;    
  18.   }    
  19.   return self;    
  20. }    
  21.     
  22. - (void)dealloc {    
  23.   TT_RELEASE_SAFELY(_URL);    
  24.   TT_RELEASE_SAFELY(_smallURL);    
  25.   TT_RELEASE_SAFELY(_thumbURL);    
  26.   TT_RELEASE_SAFELY(_caption);    
  27.   [super dealloc];    
  28. }    
  29.     
  30. - (NSString*)URLForVersion:(TTPhotoVersion)version {    
  31.   if (version == TTPhotoVersionLarge) {    
  32.     return _URL;    
  33.   } else if (version == TTPhotoVersionMedium) {    
  34.     return _URL;    
  35.   } else if (version == TTPhotoVersionSmall) {    
  36.     return _smallURL;    
  37.   } else if (version == TTPhotoVersionThumbnail) {    
  38.     return _thumbURL;    
  39.   } else {    
  40.     return nil;    
  41.   }    
  42. }    
  43.     
  44. @end  

五、Displaying a Photo Album

Create a subclass of TTThumbsViewController and import your Photo Source class.
AlbumController.h

C++代码
  1. #import       
  2.     
  3. @interface AlbumController : TTThumbsViewController {    
  4.     NSArray *images;    
  5. }    
  6. @property (nonatomic, retain) NSArray *images;    
  7.     
  8. @end  

Create an NSArray for your Photos in your Album Controller implementation file by importing PhotoSource.h and Photo.h. In Three20, the URL for local items inside of your App Bundle is the bundle:// protocol. Later we will change to the http protocol for web-based photos.

For each photo, you simply create a Photo object and provide the photo’s width, height, location and thumbnail location. You also have the option of providing a caption for each photo if you wish.

C++代码
  1. #import "AlbumController.h"    
  2. #import "PhotoSource.h"    
  3. #import "Photo.h"    
  4. @implementation AlbumController    
  5. @synthesize images;    
  6.     
  7. -(void)createPhotos {    
  8.     images = [[NSArray alloc] initWithObjects:    
  9.                       [[[Photo alloc] initWithURL:@"bundle://photo1.jpg" smallURL:@"bundle://photo1_t.jpg"    
  10.                             size:CGSizeMake(320, 212)] autorelease],    
  11.                       [[[Photo alloc] initWithURL:@"bundle://photo2.jpg" smallURL:@"bundle://photo2_t.jpg"    
  12.                             size:CGSizeMake(320, 212)] autorelease],    
  13.                       [[[Photo alloc] initWithURL:@"bundle://photo3.jpg" smallURL:@"bundle://photo3_t.jpg"    
  14.                             size:CGSizeMake(319, 317)] autorelease],    
  15.                       [[[Photo alloc] initWithURL:@"bundle://photo4.jpg" smallURL:@"bundle://photo4_t.jpg"    
  16.                             size:CGSizeMake(320, 212)] autorelease],    
  17.                       [[[Photo alloc] initWithURL:@"bundle://photo5.jpg" smallURL:@"bundle://photo5_t.jpg"    
  18.                             size:CGSizeMake(319, 319)] autorelease],    
  19.                       [[[Photo alloc] initWithURL:@"bundle://photo6.jpg" smallURL:@"bundle://photo6_t.jpg"    
  20.                             size:CGSizeMake(320, 212) caption:@"Rainbow"] autorelease],    
  21.                       [[[Photo alloc] initWithURL:@"bundle://photo7.jpg" smallURL:@"bundle://photo7_t.jpg"    
  22.                             size:CGSizeMake(320, 212)] autorelease],    
  23.                       [[[Photo alloc] initWithURL:@"bundle://photo8.jpg" smallURL:@"bundle://photo8_t.jpg"    
  24.                             size:CGSizeMake(320, 212)] autorelease],    
  25.                       [[[Photo alloc] initWithURL:@"bundle://photo9.jpg" smallURL:@"bundle://photo9_t.jpg"    
  26.                             size:CGSizeMake(320, 317)] autorelease],    
  27.                       [[[Photo alloc] initWithURL:@"bundle://photo10.jpg" smallURL:@"bundle://photo10_t.jpg"    
  28.                             size:CGSizeMake(320, 212)] autorelease],    
  29.                       nil];    
  30. }  

In your ViewDidLoad Method set up your photoSource to an instance of the Photo Source we created earlier with the NSArray of Photos.

C++代码
  1.  - (void)viewDidLoad {    
  2.      [self createPhotos]; // method to set up the photos array    
  3.    self.photoSource = [[PhotoSource alloc]    
  4.      initWithType:PhotoSourceNormal    
  5.      title:@"Hawaii"    
  6.      photos:images    
  7.      photos2:nil    
  8.    ];    
  9. }  

六、Displaying a Single Photo

Displaying a single photo by clicking on one from the Thumbnail viewer is provided to you for free by Three20. In addition, the library also provides all of the native functions such as pinch-to-zoom, swiping to navigate and tapping to hide/show the navigation arrows and back button.

七、Using Remote Web Photos from Flickr

In order to switch from using photos stored in our app’s bundle, we simply need to change all the URLs for our photos in the array. Our new createPhotos method now looks like this:

C++代码
  1. -(void)createPhotos {    
  2.     images = [[NSArray alloc] initWithObjects:    
  3.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4066/4653156849_0905e6b58e_o.jpg"    
  4.                        smallURL:@"http://farm5.static.flickr.com/4066/4653156849_0d15f0e3f0_s.jpg"    
  5.                              size:CGSizeMake(320, 212)] autorelease],    
  6.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4065/4653156973_a305372efd_o.jpg"    
  7.                        smallURL:@"http://farm5.static.flickr.com/4065/4653156973_d112fb6853_s.jpg"    
  8.                              size:CGSizeMake(320, 212)] autorelease],    
  9.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4023/4653774402_05e6acd995_o.jpg"    
  10.                        smallURL:@"http://farm5.static.flickr.com/4023/4653774402_88849684b5_s.jpg"    
  11.                              size:CGSizeMake(319, 317)] autorelease],    
  12.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4009/4653157237_4bd3699297_o.jpg"    
  13.                        smallURL:@"http://farm5.static.flickr.com/4009/4653157237_c2f5f59e0d_s.jpg"    
  14.                              size:CGSizeMake(320, 212)] autorelease],    
  15.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4044/4653774662_1a103ab5fd_o.jpg"    
  16.                        smallURL:@"http://farm5.static.flickr.com/4044/4653774662_32d8808e1c_s.jpg"    
  17.                              size:CGSizeMake(319, 319)] autorelease],    
  18.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4005/4653157447_51917fed5c_o.jpg"    
  19.                        smallURL:@"http://farm5.static.flickr.com/4005/4653157447_743afc84db_s.jpg"    
  20.                              size:CGSizeMake(320, 212)] autorelease],    
  21.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4065/4653774874_9c16b4c8a7_o.jpgg"    
  22.                        smallURL:@"http://farm5.static.flickr.com/4065/4653774874_43439783d1_s.jpg"    
  23.                              size:CGSizeMake(320, 212)] autorelease],    
  24.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4047/4653157663_8a7cfcb79e_o.jpg"    
  25.                        smallURL:@"http://farm5.static.flickr.com/4047/4653157663_3c5da970f3_s.jpg"    
  26.                              size:CGSizeMake(320, 212)] autorelease],    
  27.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4041/4653775116_5c241b8a6c_o.jpg"    
  28.                        smallURL:@"http://farm5.static.flickr.com/4041/4653775116_9e9b1e6969_s.jpg"    
  29.                              size:CGSizeMake(320, 317)] autorelease],    
  30.                        [[[Photo alloc] initWithURL:@"http://farm5.static.flickr.com/4034/4653774014_c2154f20bb_o.jpg"    
  31.                        smallURL:@"http://farm5.static.flickr.com/4041/4653775116_9e9b1e6969_s.jpg"    
  32.                             size:CGSizeMake(320, 212)] autorelease],    
  33.                        nil];    
  34. }  

A Complete Photo Album

As you can see, we now have a full featured gallery that we can use in an app to show pictures from either the web or from our app’s bundle. Three20 gives us a simple way to add a photo gallery feature to your app without having to do any of the difficult work.

posted @ 2011-12-22 10:44  印错版的RMB  阅读(593)  评论(0编辑  收藏  举报