If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!
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 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 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 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 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 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.
Creating a Photo Source
Our next step is to create an object that the TTPhotoViewController can use to figure out what photos it should display. In Three20, we do that by creating an object that implements the TTPhotoSource protocol. The definition for the TTPhotoSource protocol looks something like this:
@protocol TTPhotoSource <TTModel, TTURLObject> @property (nonatomic, copy) NSString* title; @property (nonatomic, readonly) NSInteger numberOfPhotos; @property (nonatomic, readonly) NSInteger maxPhotoIndex; - (id<TTPhoto>)photoAtIndex:(NSInteger)index; @end |
So we need to return a title for the set of photos (used in the thumbnail view of the Photo View Controller), the number of photos to display (and the max index), and finally a method to return a TTPhoto at a particular index.
TTPhotoSource is built so that you can retrieve the information on which photos to display over the network as well. However, for the purposes of this tutorial we’re take a simple route and just hard-code which images to display straight into our app – therefore we can bypass the remote downloading capability.
So let’s create an object that implements TTPhotoSource. 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 PhotoSet.m (and make sure also create PhotoSet.h is selected), and click Finish.
Then replace PhotoSet.h with the following:
#import <Foundation/Foundation.h> #import "Three20/Three20.h" @interface PhotoSet : TTURLRequestModel <TTPhotoSource> { NSString *_title; NSArray *_photos; } @property (nonatomic, copy) NSString *title; @property (nonatomic, retain) NSArray *photos; + (PhotoSet *)samplePhotoSet; @end |
Nothing too special here – we declare two properties / instance variables to store the title of our photo set and contain the list of photos. We also have a static method to create a sample photo set that we’ll use later on in the app.
Note that the class derives from TTURLRequestModel. This is because the TTPhotoSource protocol requires us to implement the TTModel and TTURLObject protocols as well, and deriving from this class makes taking care of that a lot easier.
Next go to PhotoSet.m and replace it with the following:
#import "PhotoSet.h" #import "Photo.h" @implementation PhotoSet @synthesize title = _title; @synthesize photos = _photos; - (id) initWithTitle:(NSString *)title photos:(NSArray *)photos { if ((self = [super init])) { self.title = title; self.photos = photos; for(int i = 0; i < _photos.count; ++i) { Photo *photo = [_photos objectAtIndex:i]; photo.photoSource = self; photo.index = i; } } return self; } - (void) dealloc { self.title = nil; self.photos = nil; [super dealloc]; } #pragma mark TTModel - (BOOL)isLoading { return FALSE; } - (BOOL)isLoaded { return TRUE; } #pragma mark TTPhotoSource - (NSInteger)numberOfPhotos { return _photos.count; } - (NSInteger)maxPhotoIndex { return _photos.count-1; } - (id<TTPhoto>)photoAtIndex:(NSInteger)photoIndex { if (photoIndex < _photos.count) { return [_photos objectAtIndex:photoIndex]; } else { return nil; } } @end |
First we create a constructor that takes a title and a list of photos. We squirrel those off, and then we go through each photo object and set its photo source to ourselves, and the index to the position of the photo in our list. If you recall, these are the two properties in TTPhoto that we said we’d mention later.
Next we have to implement a couple methods in TTModel that would be handy if we were retrieving the list of photos from a remote source. Since we’re hardcoding them in, we just return that we’ve already loaded them and go on our way!
Finally we have the most important methods: the required TTPhotoSource methods. However these are quite simple to implement – we just return the appropriate photo from the array.
Adding Some Photos
The next thing we need to do is actually add some photos to work with into the project! You can use some sample photos that I have gathered for this tutorial, or you can use your own. If you create your own, for each photo make a thumbnail versions 75×75, a small versions the size of the iPhone screen (in portrait or landscape), and a large version as large as you’d like (and upload the large version to a web server somewhere).
Once you’ve downloaded or created the images, drag them to the Resources folder in your project, make sure “Copy items into destination group’s folder (if needed)” is checked, and click add. Then add the following code to the bottom of PhotoSet.m (you’ll need to tweak this if you created your own images):
static PhotoSet *samplePhotoSet = nil; + (PhotoSet *) samplePhotoSet { @synchronized(self) { if (samplePhotoSet == nil) { Photo *mathNinja = [[[Photo alloc] initWithCaption:@"Math Ninja" urlLarge:@"http://www.raywenderlich.com/downloads/math_ninja_large.png" urlSmall:@"bundle://math_ninja_small.png" urlThumb:@"bundle://math_ninja_thumb.png" size:CGSizeMake(1024, 768)] autorelease]; Photo *instantPoetry = [[[Photo alloc] initWithCaption:@"Instant Poetry" urlLarge:@"http://www.raywenderlich.com/downloads/instant_poetry_large.png" urlSmall:@"bundle://instant_poetry_small.png" urlThumb:@"bundle://instant_poetry_thumb.png" size:CGSizeMake(1024, 748)] autorelease]; Photo *rpgCalc = [[[Photo alloc] initWithCaption:@"RPG Calc" urlLarge:@"http://www.raywenderlich.com/downloads/rpg_calc_large.png" urlSmall:@"bundle://rpg_calc_small.png" urlThumb:@"bundle://rpg_calc_thumb.png" size:CGSizeMake(640, 920)] autorelease]; Photo *levelMeUp = [[[Photo alloc] initWithCaption:@"Level Me Up" urlLarge:@"http://www.raywenderlich.com/downloads/level_me_up_large.png" urlSmall:@"bundle://level_me_up_small.png" urlThumb:@"bundle://level_me_up_thumb.png" size:CGSizeMake(1024, 768)] autorelease]; NSArray *photos = [NSArray arrayWithObjects:mathNinja, instantPoetry, rpgCalc, levelMeUp, nil]; samplePhotoSet = [[self alloc] initWithTitle:@"My Apps" photos:photos]; } } return samplePhotoSet; } |
This is just a helper method to create a photo set with four hard-coded images, using the constructors we created for the classes.
Creating the TTPhotoViewController
Believe it or not, that was the hardest part – everything from here on out is cake.
Let’s start by creating a TTPhotoViewController. 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 PhotoViewController.m (and make sure also create PhotoViewController.h is selected), and click Finish.
Replace PhotoViewController.h with the following:
#import <Foundation/Foundation.h> #import <Three20/Three20.h> @class PhotoSet; @interface PhotoViewController : TTPhotoViewController { PhotoSet *_photoSet; } @property (nonatomic, retain) PhotoSet *photoSet; @end |
Here we simply derive from TTPhotoViewController and keep track of the PhotoSet we wish to display.
Then replace TTPhotoViewController.m with the following:
#import "PhotoViewController.h" #import "PhotoSet.h" @implementation PhotoViewController @synthesize photoSet = _photoSet; - (void) viewDidLoad { self.photoSource = [PhotoSet samplePhotoSet]; } - (void) dealloc { self.photoSet = nil; [super dealloc]; } @end |
All we have to do here is set the photoSource property (part of TTPhotoViewController) to our class that implements TTPhotoSource in viewDidLoad. That’s it – yowza!
So let’s get this view controller displayed so we can admire all our cool photos!
Displaying the TTPhotoViewController
The last step is to replace PhotoViewerAppDelegate.m with the following:
#import "PhotoViewerAppDelegate.h" #import "PhotoViewController.h" @implementation PhotoViewerAppDelegate @synthesize window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[TTURLRequestQueue mainQueue] setMaxContentLength:0]; TTNavigator *navigator = [TTNavigator navigator]; navigator.window = window; TTURLMap *map = navigator.URLMap; [map from:@"tt://appPhotos" toSharedViewController:[PhotoViewController class]]; [navigator openURLAction:[TTURLAction actionWithURLPath:@"tt://appPhotos"]]; [window makeKeyAndVisible]; return YES; } - (void)dealloc { [window release]; [super dealloc]; } @end |
The real meat is in application:didFinishLaunchingWithOptions. The first thing we do here is set the maximum content length of the TTURLRequestQueue to 0, which means unlimited. If we forget to do this, Three20 will retrieve an error if we try to retrieve a file that is over a set limit. This is intended to warn you in case you didn’t mean to download something that big, but we don’t want those restrictions for the sake of this tutorial.
Next we start up a TTNavigator and a mapping from the tt://appPhotos URL to our PhotoViewController, and then navigate to that URL. If you’re unfamiliar how this works, you may wish to review the Introduction to Three20 tutorial.
And that’s it! Compile and run the sucker, and you should be able to navigate through your set of images with style! You’ll notice that the app shows the small images that ship with the app at first, then downloads the high res images in the background for you. Pretty cool, eh?
Where To Go From Here?
Here is a sample project with all of the code we’ve developed in the above tutorial.
The TTPhotoViewer is just one of the many great pieces of functionality available in Three20. A great way to get an overview of what’s available is to go through the TTCatalog project that comes with Three20.
Additionally, if you want to make a photo viewer but don’t want to use Three20, you could always write your own. The UIScrollView class actually contains much of the functionality to make this possible – see WWDC talk #104 for some great info on this.
If you have any comments or questions just drop a line below – and let me know how you’re using or planning to use Three20 in your apps!
Category: iPhone











thanks for the new tutorial Ray. I’m following you now…
hello.!
very understandable explanation.
I’m trying to put images that I saved to disk within TTPhotoViewController …
but only shows those of the bundle or the web.
I write the path as in other occasions it does not work …
any idea how to pass the parameter??
There are (or were) a couple of places where the latest Three20 does not correctly handle the updated SDK. ie, it says “if you have the 3.2 SDK, then your device will be able to invoke 3.2 methods” which is not true if you’ve set the deployment version to 3.1.3 or earlier (to support an old iPod Touch)
The symptom was crashing whenever it tried to hide the status bar.
i find it funny that we’re tackling the same problems at the same time. I had to implement this a few weeks ago and I had to add a global state to pictures in my app so i had to modify a lot more of the framework .. i went as far as changing ttphotoviewcontroller and ttthumbsviewcontroller. i ended up splitting the framework in 2 parts one had the bulk needed and was still static and i added the dynamic content to the one imported .. ttthumbs stuff and ttphotoviewcontr.. Good job with the tutorial
Hi Ray,
In one of my project I have used this very useful TTPhotoViewController. But I have an issue that I am not able to solve :
I wanted to customize the entire navigation controller by putting an image as background of it. After some research I have found that the best solution was to create a category for UINavigationBar where I put my own implementation of the drawRect. It works well. Except one thing : now when the controller is disaplyed my images are not in full screen, I have to click on the image to set it in full screen. I checked that the style of the navigation bar was Transluscent but even with that the photos refuse to display the top of them behind the navigationcontroller. Moreover, there is not the same issue with the toolbar that I have also customized using an image : the photos are correctly taking the space behind it.
I just can’t find what I have to do to solve that little glitch. So if you have the solution I would be glad to hear it ;)
Is that possible to use image picker in iPad ?
I know that UIPopoverController should be used, but a lot problems there, anyone succeed this ?
if([UIImagePickerController isSourceTypeAvailable:sourceType]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = sourceType;
picker.delegate = self;
//picker.allowsImageEditing = NO;
//[self presentModalViewController:picker animated:YES];
//[picker release];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
self.popoverController = popover;
popoverController.delegate = self;
[popoverController presentPopoverFromRect:CGRectMake(100, 100, 200, 300)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
//release the popover conten
[picker release];
[popover release];
}
Another problem notes here
http://stackoverflow.com/questions/2617541/uiimagepicker-on-full-screen-on-ipad/3209997#3209997
This is easy when you have known image names and their urls, but what about when you don’t know the names of the images you need to call.
For example I’m using JSON to call back an array of images from a server, I can see all the urls for these unknown image in my NSLog, but how can I pull these out and display them, atm it only displays the last image in the downloaded array.
Thanks
yes, I have resolved to use image picker in iPad.
It is pity that iPad does not have camera, when will it has ?
Today, go to buy one iPad, more than 700 USD (wifi + 16 G ) , what money they earn !
@gabby: There’s another prefix for the documents directory, try this out: documents://
@Jeff: Hm interesting. I’d love to modify the sample project to switch to a 3.1.3 deployment target and run it on a 3.1.3 device and see if the issue you mentioned still exists. If anyone gets a chance to try this, please let us know the results!
@Alex: Yeah it is funny how that works sometimes :] Cool sounding project too!
@olinsha: Not sure without seeing the code – sounds like a matter of debugging!
@Forrest: I’ve used the image picker on the iPad by putting it within a UIPopoverController. What issues are you having? Yeah the iPad is expensive, it is a very nice device though!
@Andre: In this tutorial, I just hard-coded the photo source in, but Three20 is designed so you can also retrieve the photo source over a network connection. If you take a look at the TTCatalog example that comes with Three20, you’ll see a “MockPhotoSource” class that illustrates (kind of) where you’d put the code to load the list of images from a network connection.
Thanks for the response Ray, but I can’t find anywhere to load these urls from a json file, it still only load the first image in the list.
Any chance of a mod to your source to show multiple images without hard coding.
Ok, nevermind I’ve now sorted it by dynamically adding MockPhoto for each each image in my JSON file.
[_murl addObject:[[[MockPhoto alloc]
initWithURL:_urlMainString
smallURL:_urlThumbString
size:CGSizeMake(1733, 2608)]autorelease]];
Regards
@Andre: Cool glad you got it working! I am considering writing an update to this tutorial to talk about dynamically loading the list of images in the future as well.
That would be cool, can’t believe I’ve been messing with it for 3 days, took 1 day away from it and 5 mins later I got it sorted. Brain must have been tired of looking at the code too long. LOL.
Hello Ray,
first of all, thanks for the great tutorial. That stuff works great! I’m having a hard time though, porting it to a device. While it works fine on the simulator, I get these Linker errors when compiling for iPhone or the iPod Touch:
Undefined symbols:
“___restore_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) allocWithZone:] in libThree20Core.a(TTEntityTables.o)
“___save_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) allocWithZone:] in libThree20Core.a(TTEntityTables.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
Do you have an idea? This looks so cryptic.
Thanks!
Hey Ray, great tutorial! Thanks for it. I was wondering if you knew of a way to open straight into the thumb view instead of into a specific image? it seems it wouldn’t be a large change, but i can’t seem to figure anything out with the api. Thanks again.
Sorry about bugging you about my stuff earlier. I fixed it by adjusting the Project Settings to the Target Settings. Since this was a completely new Project, I thought everything should compile just fine, anyway, now it does. Maybe this helps someone…
I’ve incorporated the use of a FullSized image, a Thumbnail Image and a Small Image into my app, now I noticed that when viewing the thumbView the images were dispro’ed and didn’t look very nice, especially as the image I am displaying don’t have backgrounds, it turns out it’s using my Thumbnails image instead of my small image so I went looking and found the following on line 79 of TTThumbsTableViewCell.m
thumbView.thumbURL = [photo URLForVersion:TTPhotoVersionThumbnail];
So I changed this line to the following:
thumbView.thumbURL = [photo URLForVersion:TTPhotoVersionSmall];
and hey presto nice looking small images in TableView mode.
Turns out (well in my version of Three20) that, while loading the large image it displays the thumbnail first while it’s loading the large image data, but also using the thumbnail image in tableView mode.
Hope this helps out.
Keep up with the tutorials Ray and thanks.
@Icky: Yeah I had the same problem a while back, and I agree that is cryptic at first sight. In my case, it was that the Three20 projects were using a different base SDK than my project’s base SDK.
@Jesse: If you look at the TTCatalog sample project that comes with Three20, check out the second item in the list: “Photo Thumbnails”. This demonstrates how to launch straight to the thumbnail viewer. Basically you just make a TTThumbsViewController rather than a TTPhotoViewController, and is nice and simple!
@Andre: Cool thanks for sharing! :]
Another one for you Ray.
When viewing ThumbnailView, if you start off in portrait mode and rotate to landscape mode then the thumbnails are placed about 12px under the navigationBar so I updated the TTThumbsViewController.m file with the following and now it show approx 4px below the navBar on both portrait & landscape.
- (void)updateTableLayout {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if ((orientation == UIInterfaceOrientationLandscapeLeft) || (orientation == UIInterfaceOrientationLandscapeRight)) {
self.tableView.contentInset = UIEdgeInsetsMake(TTBarsHeight()+16, 0, 0, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(TTBarsHeight(), 0, 0, 0);
}else {
self.tableView.contentInset = UIEdgeInsetsMake(TTBarsHeight()+4, 0, 0, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(TTBarsHeight(), 0, 0, 0);
}
}
Don’t think my last correction is working properly though, thumbnails showing correctly but it still seems to be using the wrong images to display the main image, always cuts wider images off at the sides when comming from thumbnailView.
Regards
Sorry, the above will only work if your NavigationBar is translucent in colour, if you have set a tint on your thumbview navbar then stick to the original code.
Regards
@Andre: Cool for that as well, thanks again for sharing!
hello,
I’ve tried changing the base sdk in all the sub projects. I can’t seem to get your sample project to build, i get the following errors, any ideas why I cant build it? I’m on the latest sdk.
“___restore_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
“___save_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) allocWithZone:] in libThree20Core.a(TTEntityTables.o)
@Jon: Yep, as mentioned in the comments above, you have to go through and fix up each Three20 project to use the same base SDK as your main project.
Hi Ray, you’ve got some great tutorials here on your site and it’s great your sharing them with others.
I did forget to mention though that the project I’ve nearly finished using the photoviewer is actually for the iPad and not the iPhone, and thinking about it some things may be different like positioning.
Regards
Andre
Getting warning and error
warning: ‘UIActionSheet’ may not respond to ‘-showFromBarButtonItem:animated:’
Error “_UIApplicationDidEnterBackgroundNotification”, referenced from:
Any body here to help me
Solved
I want to show thumbnail first and then big image. also want some changes in navigation bar of big photo. how can o do it
@Rajiv: To show thumbnail first, you can just use the Three20 TTThumbsViewController instead. To change the navigation bar, you’ll probably have to modify the Three20 source to get that to work. I’ve done it before to put an extra button in the bottom toolbar for the Three20 photo viewer, it’s not that bad.
Is Apple still rejecting apps that use the Three20 frameworks ? I’m just using TTURLRequest( but have imported all projects – as per the instructions) but I’m worried about our app getting rejected because of all the cases I read online.Anybody ?
@A3: AFAIK that was true in the past but is OK now. If anyone hears differently please let me know!
Hey Ray! Great Tutorial! Thanks!!
I am not sure if this is beyond the scope of this particular tutorial, but I am wondering how to implement this photo gallery inside of a tableview, i.e. Table view on first page has selector A, B, and then Photo Page. When you click on “Photo Page” it will then take you to your gallery. I am really having trouble finding any information for how to set this particular method up.
Any help is GREATLY appreciated!
Thanks again!
Could you point me in the direction of a place where I could find this information?
@Jessie: It sounds like you may be looking for just a basic tutorial on how to use UITableView? I recommend the book “Beginning iPhone Development” by Dave Mark and Jeff LaMarche, which does a great job explaining how to use that.
Thanks Ray. I’ve actually gotten my app developed using the table view already, I’m just having issues inserting the photo gallery. Sounds like I’ve got a little more research to do…
Thanks for your help! :)
hi all,
Actually i install photo gallery in my app and put back button in navigation. The button works fine but loads the style of three20 gallery as it hide my tabbar navigation, background color etc.
thanks,
Thanks for your tutorial Ray!! I got everything to work following your tutorial…. but have a hard time on dynamically loading image info etc from json format…….
by any chance you had already done below sample or help can help on setting image info up with your “samplePhotoSet” sample?
————————————-
@Andre: Cool glad you got it working! I am considering writing an update to this tutorial to talk about dynamically loading the list of images in the future as well.
————————————–
Thanks…
Hello Rajiv,
Could you please me. I am also getiing the
Error “_UIApplicationDidEnterBackgroundNotification”, referenced from:
Thank you
@Rajiv: Did you have a question, or is that just a comment?
@Bobby: I don’t have a sample project for that, but if you look at the Three20 sample project “TTCatalog”, take a look at the “MockPhotoSource” implementation, which will point you in the right direction.
@palas: That sounds like something is trying to use the UIApplicationDidEnterBackgroundNotification symbol on a SDK that doesn’t have that symbol defined (such as pre 4.0). The code needs to check that the symbol is defined first with code like this:
if (&UIApplicationDidEnterBackgroundNotification) { // Woot symbol is available, so let's use it! }@Ray: Hi Ray its a question.
Im trying to wrap my head against this..
Instead of having the images from http or a bundle, they are stored as a blob in a sqlite database.
I could fetch the image locally..
image = [[[UIImage alloc] initWithData:[_rs dataForColumn:@"image"]] autorelease];
However, im confused on which part of three20 do I change to reflect this? Would it be in TTPhotoSource or TTPhoto?
TIA,
rupert
Hi,
Thank you very much for this tutorial.
I followed all the steps but I can’t launch the application. There are no errors when compiling but when the iPhone simulator starts, it takes me back to the home screen.
I’m using XCode 3.2 with iPhone Simulator 4, I changed that for all the imported project.
Can you help me to fix that please ?
Thanks :-)
Hi,
I m very new to Iphone dev as well as the Three20 library….
I was able to implement it and play with it especially the TTThumbsViewController (I just use the sample that came with the three20)
So here’s my problem… :)
my app uses a tabBarNavigation that contains a customized background…
I would like to know how to hide (or not display) the title when the thumbnails are displayed.
And how to remove it (when you click onto a picture to get the full size) but set the Back button?
As I said, I used the sample called “TTCatalog”…
Stan
@Rajiv: Lol… well what is the question?
@rupert: Hmm… the three20 guys would know this better than me, but looking at it I’m not sure if there’s a simple way to use the TTPhotoView with images from a non-url source. I looked into the three20 code a bit and it looks like one way to accomplish this would be to define your own URL scheme (such as sqlite://image/5) and modify TTURLCache to detect/handle this URL scheme in imageForURL to load the image from the database instead…
@bnablios: Have you tried the sample project to see if that works for you? If so try comparing your project to the sample project to see if there are any differences.
@Stan: AFAIK for mods like that, you’d have to tweak the Three20 code for those classes or subclass them.
Hello,
Thank you for your answer. I’ve fixed that, now the application is working but I still have a problem, I’m using three20 inside a TabBar application but when I click on the tab that contains thumbnails, the bottom bar disappears. Can you help me please to fix that?
Thank you very much
hellow Ray,
Could you please me.I am also getiing the
“_UIApplicationDidEnterBackgroundNotification”, referenced from:
_UIApplicationDidEnterBackgroundNotification$non_lazy_ptr in libThree20UINavigator.a(TTBaseNavigator.o)
(maybe you meant: _UIApplicationDidEnterBackgroundNotification$non_lazy_ptr)
I do not know how to solve,expecting your message.
thank you
@Ray: question is that, when three20 loads it disappear my Tabbar
@bnabilos, @Rajiv: Regarding the tab bar disappearing, this thread from the three20 Google groups may help.
@hao: According to this thread, make sure that you have the Base SDK for your project and all of the three20 projects set to iPhone Device 4.0.
@Ray: thank you very much, I fixed that :-)
I still have one problem, the landscape mode is not working. When I rotate the simulator, the content stays in the portrait mode. There is a way to fix that ?
Thanks a lot :-)
@bnablios: I just tried out the sample project and it rotates correctly in both portrait and landscape mode, so it must be something specific to your project. Make sure you’ve implemented shouldAutorotateToInterfaceOrientation in your view controller to return YES, if applicable.
This Sample code runs on simulator well but when i want to install this on my iphone OS4.0 it crashes
due to memory leak or some problem.
debugger console shows EXC_BAD_INSTRUCTION error in this function…
+ (TTURLRequestQueue*)mainQueue {
if (!gMainQueue) {
gMainQueue = [[[TTURLRequestQueue alloc] init] autorelease];
}
return gMainQueue;
}
Please reply me when you are available.
regards
Asad
@ray:thank you very much!i will try again
@ray:thanke you very much! i solved
Hi
i want to add a save button to a TTPhotoViewController so that i a user can save the photo to photos album.
please help me in this problem.
Ray,
I’ve been mucking around with three20 for a couple of months, and have integrated it into my app. I have a view that uses TTTabBar. One of the tabs needs to display thumbnails, and I’ve tried integrating TTThumbsViewController, but it just doesn’t want to work. The basic problem seems to be that PhotoViewer and ThumbsViewer are fundamentally reliant on being loaded initially by TTNavigator. However, because I’m using TTTabBar, I am having to manually load the panel, when the tab is tapped, via a [self.view addSubview:...]. This bypasses all of the complex logic in the super classes (ModelView, etc.) that manage the view and loading. The result is nada. Nothing loads.
Do you have any suggestions? I’ve posted to the Google group, and not received any hints. I’m to the point of rolling my own simple viewer, but I’d really like to be able to take advantage of all of the goodies in Photo- and ThumbsView, without having to take all the time that would be involved to build my own.
If you have *any* suggestions, I’m all ears. This would save me a tremendous amount of time and effort.
Thanks!
@Asad: It looks like you’re trying to create a global variable for a singleton mainQueue, however when you create the variable you’re marking it as autorelease. This means as soon as the variable goes out of scope, it will be released, but the global variable will still be pointing to a (now released) variable.
It looks like you want to remove the call to autorelease here.
In fact, I just looked at TTURLRequestQueue.h in my version of Three20, and there is no call to autorelease… maybe a bug in the version of Three20 you have…?
@hao: w00t!
@AsadU: To do that you just need to add a new Photo to the photos array in the PhotoSet. As for the button, you can modify TTPhotoViewController to add a button on the bottom bar or the like.
@NukemHill: I did some brief playing around with this, and I was able to get a TTPhotoViewController to show up inside an inner view of a view controller by writing something like this:
The problem is the view controller acts kind of funky in this state – I think some of the code may have been written with the assumption that it’s always a full screen view controller. It’s probably fixable by hacking the code a bit though.
Alternatively, if that gets too hairy there’s a good WWDC talk on rolling your own image views you might want to check out: WWDC Session #104, Designing Apps with Scroll Views.
Hi,
Sir I am using your tutorial three20 , I am facing porblem in the relative path . plaese guide me with example.
Thanks,
Muzammil
Hi!
Is there a way to use it with nib’s? I have a tab bar containing the Images tab and I’d like to add the photogallery view controller as tab bar controllers navigation controllers view controller, but I can’t create a suitable version of PhotoViewController for this.
Kristjan
Hi Sir,
I am using your sample code of PhotoViewer , PhotoViwer gives me this error when I run this application in simulator. Please give me As I have tried it very hard to solve this problem.
// error given by PhotoViwer
2010-09-07 12:59:56.958 PhotoViewer[4527:207] +[UIViewController ttAddNavigatorController:]: unrecognized selector sent to class 0x1e7b3f8
2010-09-07 12:59:56.961 PhotoViewer[4527:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘+[UIViewController ttAddNavigatorController:]: unrecognized selector sent to class 0x1e7b3f8′
*** Call stack at first throw:
(
0 CoreFoundation 0x025f0919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x0273e5de objc_exception_throw + 47
2 CoreFoundation 0x025f24eb +[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0×02562116 ___forwarding___ + 966
4 CoreFoundation 0x02561cd2 _CF_forwarding_prep_0 + 50
5 PhotoViewer 0×00067867 -[TTURLMap setObject:forURL:] + 215
6 PhotoViewer 0x00067ca4 -[TTURLMap objectForURL:query:pattern:] + 315
7 PhotoViewer 0x0006e569 -[TTBaseNavigator viewControllerForURL:query:pattern:] + 640
8 PhotoViewer 0x0006dae7 -[TTBaseNavigator openURLAction:] + 843
9 PhotoViewer 0x00001d17 -[PhotoViewerAppDelegate application:didFinishLaunchingWithOptions:] + 316
10 UIKit 0x003c3543 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
11 UIKit 0x003c59a1 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 346
12 UIKit 0x003cf452 -[UIApplication handleEvent:withNewEvent:] + 1958
13 UIKit 0x003c8074 -[UIApplication sendEvent:] + 71
14 UIKit 0x003ccac4 _UIApplicationHandleEvent + 7495
15 GraphicsServices 0x02e56afa PurpleEventCallback + 1578
16 CoreFoundation 0x025d1dc4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
17 CoreFoundation 0×02532737 __CFRunLoopDoSource1 + 215
18 CoreFoundation 0x0252f9c3 __CFRunLoopRun + 979
19 CoreFoundation 0x0252f280 CFRunLoopRunSpecific + 208
20 CoreFoundation 0x0252f1a1 CFRunLoopRunInMode + 97
21 UIKit 0x003c5226 -[UIApplication _run] + 625
22 UIKit 0x003d0b58 UIApplicationMain + 1160
23 PhotoViewer 0x00001bb8 main + 102
24 PhotoViewer 0x00001b49 start + 53
)
terminate called after throwing an instance of ‘NSException’
@Muzammil: I just tried running the sample project here and it ran fine without any errors. Are you sure you didn’t modify it at all?
@Kristjan: As I mentioned in my reply to @NukemHill above, as far as I can tell you’ll have to do some hacking in the Three20 source to get this to work properly.
I found that three20 could not run on ipod with ios3.1.1.
Hi!, very very nice tutorial. Thank’s for sharing. I’m trying to find the best way to solve this :
quoting you –
TTPhotoSource is built so that you can retrieve the information on which photos to display over the network as well. However, for the purposes of this tutorial we’re take a simple route and just hard-code which images to display straight into our app – therefore we can bypass the remote downloading capability.
But I’m messing around tones of code and i know I’m not doing it weel, could you include in your sample project the remote images loading ?
I’m completely desperate to get this feature running, as I’m learning the architecture and right coding is hard for me.
Thank You so much
i want to make Thumbnail Images a little large so that there are 3 rows on the screen for thumnail images. Like this application
http://itunes.apple.com/us/app/3d-wallpapers-lite/id359080477?mt=8
Please anyone reply me.
Hello ray
you didn’t ans me yet.
i am waiting for any suggestions and
ans.
thanks
@Asad
Please be patient, Ray is a busy man, if you can’t wait, then try using google to see if that brings any results.
You’ll have to modify the #define in one of the Thumbnail sources. If I remember correctly.
Dear Sir/Madam
i am using your code and it works perfect with me.
i am facing only one problem. i want to know how
to save the large image in Photo View Controller if i
am using the TTThumbsViewController at start up.
please reply me as soon as possible.
best regards
Asad
@Sam: Good to know, thanks for sharing!
@javi: Unfortunately I don’t have time to update this tutorial with that right now, however I will keep this in mind for the future!
@Asad: Andre is correct, for thumbnail sizes it looks like the rowHeight of the tableView is set in loadView of TTThumbsViewControlelr to kThumbnailRowHeight, which is set to 79. You should be able to change this, but you might have to change some other constants as well (looks like 75 is hardcoded in a couple places for thumbnail size).
Regarding your other question, I’m not sure what you’re trying to do…
Is this tutorial fully work in Xcode4 (IOS4.1)?
I downloaded your sample project(PhotoViewer.zip)
and successfully re-added the Three20 Library(http://github.com/facebook/three20) into your profect, and mime cannot compile correctly?
(http://www.appvertisr.com/file_3dantstudio/three20.jpg)
how can i fix it?
or can you make another new version sample project?
Thanks
I keep getting this error when I make my own plist and jpg files with Zwoptex. When I use the bear ones from the sample project it runs fine.
Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘CCSprite is not using the same texture id’
Any idea what the problem is? Thanks!
(I tried it with both the latest downloaded version of Zwoptex and the online Flash version and get the same error.)
problem solved, thanks a million Ray!
@William: Great, glad you got it working!
@Tamara: Did you mean to post this in the Cocos2D animation tutorial?
Anyway, that problem indicates that you are trying to add a sprite as a child of the spritesheet that does not come from that sprite sheet.
For example, say you have a spritesheet with a bunch of bear images, and a separate ball image. You can’t add the ball image as a child of the bear spritesheet, because they don’t come from the same image.
Let me know if that helps or if you have any further questions!
Hi Ray,
I have been googling this for a couple of days, but find no answers, I’m hoping you may have some inspiring thoughts. I am using three20 to create a photo essay of a story I made after the February earthquake in Chile.
I would like to be able to display portrait images when iPad device is in portrait orientation and landscape images when iPad device is in landscape orientation.
So there would be two versions of every image, one cropped for portrait viewing and one cropped for landscape viewing and the app would show the version that is appropriate for the orientation the device is in.
I will layout these versions separately. That way, the app would make full use of the screen in all orientations and users will read the story like a magazine.
Ideally, the view would change over to the corresponding image, staying where it is in the sequence of images, when the user rotates the device, so from portrait #4 to landscape #4 and vice versa, for example.
But, if this is not possible, jumping back to the first image whenever iPad device is rotated is acceptable as well.
Can this be done? If so, can you give some clues?
If it can not be done putting a specific image in the background with the image viewer overlaying it may also be a solution.
The idea is to give to user the experience he is reading an illustrated story in all orientations.
Thank you!
diederik
Hi Ray,
I’m having a hard time AGAIN when i porting the sample project to my device. While it works REALLY FINE on the simulator (after I changing all the base sdk in the sub projects.)…….But now I get these errors when compiling……I’m using the latest version SDK which’s 4.1
it looks like “Icky” and “Jon” question….
Undefined symbols:
“___restore_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) allocWithZone:] in libThree20Core.a(TTEntityTables.o)
“___save_vfp_d8_d15_regs”, referenced from:
+[TTEntityTables(TTSingleton) sharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) releaseSharedInstance] in libThree20Core.a(TTEntityTables.o)
+[TTEntityTables(TTSingleton) allocWithZone:] in libThree20Core.a(TTEntityTables.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
Oh, and another question…
if i want to add this sample project into my existed tabbar-based app, how should i implement it?
is there any demo that i can reference from ?
Thanks
@diederik: You can register for the UIApplicationWillChangeStatusBarOrientationNotification to get a callback when the device rotates, and switch out the image when that happens.
@William: That’s the problem that shows up if you don’t have all of the SDKs for each and every Three20 project set to the same Base SDK (if using latest version of XCode, iPhone Device 4.1).
Regarding the tabbar-based app, note in this example we were using the TTNavigator to display our PhotoViewController, but you don’t have to. PhotoViewController is a plain old View Controller, so you can add it to one of your tabs just by setting it in Interface Builder, for example.
@Ray: As you said before, there is probably some hacking needed to get this to work for the tab bar.
I didn’t manage to add PhotoViewController to one of my my tabs by setting it in the Interface Builder.
But, I haven’t given up yet :)
Hi Ray.
Thank you for this tutorial. I am having the same problem as Kristjan and William. Is there a demo/tutorial to get this working with a tab bar app, and start with ThumbnailView not ImageView? Do you have planned to write a tutorial / Demo explaining this?
Thank you.
@Tor
To use thumbsview, you just have to use TTThumbsViewController instead of TTPhotoViewController.
Hi,
Has anyone successfully implemented this on the iPad. When in portrait view it works, until we rotate to landscape, then back to portrait – it then looks like it takes on the dimension of the iphone and not scale to the dimensions of the IPad.
Help will be appreciated.
Regards,
@Oliver
Yes I have this running on iPad at full screen for showing product shots downloaded from a server which I developed for my work place.
http://img403.imageshack.us/i/imagelfk.jpg/
http://img218.imageshack.us/i/imagegzi.jpg/
Portrait & Landscape.
OK, I got it working.
Here’s what I did:
1. Opened AlbumController.xib (in Ray’s example it would be PhotoViewController.xib)
2. Opened Interface Builder’s classes library, highlighted AlbumController and in the Interface Builder’s File menu I chose “read class” files, navigated to three20/src/Three20UI/Headers, marked all the files (actually, it’s only necessary to mark TTThumbsViewController’s (TTPhotoViewController’s in Ray’s example) inheritance line file’s, but it’s easier to mark them all) and read them into the Interface Builder. Notice that AlbumControllers inheritance isn’t shown completely yet. So I repeated the process with three20/src/Three20UINavigator/Headers and three20/src/Three20UICommon/Headers to have the full inheritance to NSObject. I tried doing it with just reading three20.h, but it didn’t work for me.
3. Set the file owner’s class to AlbumController
4. Dragged Thumb View (Photo View in Ray’s example) from IB’s classes library to AlbumController.xib and connected to the files owner’s view outlet
Here is my AlbumController.m:
#import “AlbumController.h”
#import “PhotoSource.h”
#import “Photo.h”
@implementation AlbumController
@synthesize images;
-(void)createPhotos {
images = [[NSArray alloc] initWithObjects:
[[[Photo alloc] initWithURL:@”bundle://asva1.jpg” smallURL:@”bundle://asva1.jpg”
size:CGSizeMake(320, 212) caption:@”Asva fortified settlement”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://nasva1.jpg” smallURL:@”bundle://nasva1.jpg”
size:CGSizeMake(320, 212) caption: @”Nasva village”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://lossihoov.jpg” smallURL:@”bundle://lossihoov.jpg”
size:CGSizeMake(319, 317) caption: @”Kuressaare piiskopilinnuse lossihoov”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://toobriolu.jpg” smallURL:@”bundle://toobriolu.jpg”
size:CGSizeMake(320, 212) caption: @”Saaremaa toober”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://kihelkonna.jpg” smallURL:@”bundle://kihelkonna.jpg”
size:CGSizeMake(319, 319) caption: @”Kihelkonna kellatorn”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://kaarma3.jpg” smallURL:@”bundle://kaarma3.jpg”
size:CGSizeMake(320, 212) caption:@”Kaarma kirik”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://eemu2.jpg” smallURL:@”bundle://eemu2.jpg”
size:CGSizeMake(320, 212) caption:@”Eemu tuulik”] autorelease],
[[[Photo alloc] initWithURL:@”bundle://photo8.jpg” smallURL:@”bundle://photo8_t.jpg”
size:CGSizeMake(320, 212)] autorelease],
[[[Photo alloc] initWithURL:@”bundle://photo9.jpg” smallURL:@”bundle://photo9_t.jpg”
size:CGSizeMake(320, 317)] autorelease],
[[[Photo alloc] initWithURL:@”bundle://photo10.jpg” smallURL:@”bundle://photo10_t.jpg”
size:CGSizeMake(320, 212)] autorelease],
nil];
}
//Added this method to remove white space beneath the navigation bar
- (void) updateTableLayout {
self.tableView.contentInset = UIEdgeInsetsMake(5, 0, 0, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(TTBarsHeight(), 0, 0, 0);
}
- (void)viewDidLoad {
//Changes navigation bar’s color
self.navigationBarTintColor=[UIColor colorWithRed:0.09375 green:0.51953 blue:0.43360 alpha:1.0];
//Sets back buttons title
self.navigationItem.backBarButtonItem.title=@”Back to gallery”;
//It would make thumbnail view’s backround black
// self.tableView.backgroundColor=[UIColor blackColor];
[self createPhotos]; // method to set up the photos array
self.photoSource = [[PhotoSource alloc]
initWithType:PhotoSourceNormal
title:@”IMAGES”
photos:images
photos2:nil
];
}
@end
I still have some problems though:
1. Navigation bar’s color only changes in thumbnail view – in photo view it’s still black (hacking TTNavigation)
2. Tab bar’s title set in the IB gets overridden by the title set in AlbumController.m (I tried hacking TTTabItem, but still no luck)
Bu the way, to get it working on a device I had to check “Build Active Architecture Only” (and set Active Architecture to armv7 if I’m not mistaking) I also had to set Active SDK to “Device” manually.
OK, problem 2 solved:
I set title:nil, after wich tab bar items title isn’t overridden anymore and for setting navigation bars title I added to the end of viewDidLoad self.navigationItem.title=@”Title”
please help me
when i pushing to photo gallery into table view
if (indexPath.row == 1) {
AlbumController *albumController = [[AlbumController alloc] init ];//WithNibName:nil bundle:nil];
//[ self.navigationController pushViewController:albumController animated:YES];
[[TTNavigator navigator] openURLAction: [[TTURLAction actionWithURLPath:@"demo://album"] applyAnimated:YES]];
[albumController release];
} but it not came back to table view it stay in photo gallery
Nice tutorial.
But when i try to subclass TTURLRequestModel following your sample. I get this error
“_OBJC_CLASS_$_TTURLRequestModel”, referenced
Am i doing something wrong.
For people who have trouble adding Three20 to their project, http://three20.info/article/2010-10-06-Adding-Three20-To-Your-Project is a gold mine.
@Andre and @Kristjan: Wow thanks for helping out the other guys here, you guys pwn!
@ashok: First thing I’d check is that you added an entry into your TTURLMap to map from demo://album to the view controller you want to load.
@Usama: First thing I’d check for that is that you followed the instructions very carefully from the Three20 page on how to import Three20 int your project.
@Tudor: That looks useful. But I’ve also found the official instructions quite straightforward, and that’s what I usually use.
https://github.com/facebook/three20
I figuring out one way to load images from JSON results dynamically.
Following codes will load all images immediately,
- (void) viewDidLoad {
self.photoSource = [PhotoSet samplePhotoSet];
}
Actually I got JSON results, but point is that I have no idea where to put them into photoSource.
Any ideas ?
@Forrest: I’d suggest taking a look at the TTCatalog sample that comes with Three20, specifically the “Mock PhotoSource” class that illustrates how to load a list of images in a delayed manner like you would over a network connection.
I’m currently using the TTPhotoViewController to display a set of images I’m picking from URLs. When I click load the controller, the landing photo never loads, even if I wait for an hour. Then when I click the “See All” button, the ThumbsViewController appears and all other photos load apart from the landing photo and its to adjacent photos. From here, these photos only load once I start swiping through the TTPhotoViewController. Does anyone have any idea what the problem could be?
@thomas: I haven’t come across that myself. If you figure out what the problem is though, please post here so others can benefit!
Hi.
The problem I posted above was actually a thread issue. We have a thread that refreshes a list (with the load screen image) followed by a thread in the TTPhotoViewController that loads the images from the specified URLs. The second thread could not tell the other had finished until and action was taken i.e the swipe.
Thanks for a great tutorial!
Hi, great tutorial
But I want to remove the “See All” button from the navigation bar, I have tried a lot of things but with no result. I will glad if you post something that removes the “See All” button.
Thanks in advice.
Hi Ray, Very nice tutorial.
@thomas: Aha! Thanks for posting what your solution was :]
@Terente: Probably for that you’re going to have to dig into the Three20 source and change it a bit.
@macboy: Thanks!
Hi Ray, Just one question, I was using your tutorial and it works really great in my app. I was using TTHumbsViewController, and I was wondering if its possible to add it to a regular view, I mean a UIView something like [myView addSubView:TTHumbsViewController.view]; so that I can display it anywhere like a TabBar or any custom view. Thanks for any help.
@macboy: You should be able to do that in theory, however the Three20 library may make various assumptions that it takes up the whole screen, etc. that you’d have to dig in to the source to fix.
Hello Ray, Thanks for the info. As you mentioned it appears to be doable in theory, but doesn’t appear in practice. I knocked a few doors at the Three20 group in google, and nobody could confirm it. I’ll check at the source and see what i can find out. Thanks once again
@Macboy: Cool, good luck!
Hi Ray,
I have the exact same problem as Muzammil did earlier, but there doesn’t seem to be a solution mentioned because he didn’t get back to you? I have the exact same code as you do, I even copied your files over to mine at one point just to see if that would work. Your source code runs fine for me, I just cant create it myself to work for some reason. Any ideas? I’m kinda new to iPhone dev and would appreciate any advice about even how to go about finding out whats wrong.
my source:
http://www.foxxhouse.com/PhotoViewer.zip
I checked through the build settings, the only difference I could find there was that you had for your heading search path and I didn’t have anything. I attribute this to me installing Three20 with the new python script that have on their site, and tried adding the header search paths manually the old way but that didn’t change anything. Your working version and mine are both using the same Base SDK too.
But yer, yours source code works and runs fine, mine doesnt, and I cant create my own working project with Three20 from scratch.
Thanks for your time! Would really appreciate any help you can give me.
@Joseph: First thing I’d check is follow the exact instructions here on how to add Facebook to your project:
https://github.com/facebook/three20/
If you try that and are still having troubles, let me know.
Ray:
You open thePhotoViewController when the application lunched, However,if I want to open the PhotoViewController by clicking on a button,how should I do?
Thanks for yours tutorial.
I have a request :)
Can you make a tutorial to show how integrate three20 and inappsettinskit?
http://www.inappsettingskit.com/
Thanks