订阅

2010

Jul

09

使用Three20开发iPhone相册
文章类别:iPhone开发

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

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

4c36d7186999a.jpg

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.

4c36d85672457.jpg

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”.

4c36d94e2707b.jpg

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.
4c36d9a004853.jpg

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”.
4c36d9f68169e.jpg

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”.
4c36da37791c6.jpg

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.
4c36da9f1cfc2.jpg

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″.
4c36dadd61ef1.jpg

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.

4c36db4381396.jpg

二、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.

标签:iphone, three20, album
阅读全文>> | 评论(5) | 阅读(372)
相关文章:

iPhone initWithFrame: reuseIdentifier: is deprecated的解決方法 (2010-08-25)

iPhone开发笔记(二) (2010-07-31)

iPhone开发笔记(一) (2010-07-29)

iPhone开发之显示WiFi提示 (2010-07-23)

iPhone开发之全局变量的使用 (2010-07-21)

看看他们的脚印……

踏雪残情

2010-07-09 20:49:28

坐个沙发,纯支持.代码这么长.

林西老九

2010-07-10 07:24:51

那好吧,我飘过,嘿嘿,顺便二楼

ikeeptrying

2010-07-11 00:01:42

博主这么强大的说~~
佩服

keelii

2010-07-16 09:10:47

做iPhone开发公司是不是要级配一台Mac book呢!哈哈~

wuleilei

2010-07-16 13:24:38

没哦,Mac book好贵呀。
就用是普通的PC装了个苹果系统而已。

losongj

2010-09-01 14:13:27

你朋没有做好的Demo给个我,...这个我看得很吃力
谢谢
我也踩个脚印^_^

闲言碎语
靠,现在的垃圾留言也太智能了吧。 (9月7日)
不要逼我把你加入黑名单,少在这里发广告! (8月17日)
周末回家咯 (8月13日)
文章分类
最近文章
最近评论
日志归档
友情链接
其它功能
随机标签