TabBar Support of Three20 iPhone Photo Gallery

2019-02-10 15:46发布

问题:

I wend through this tutorial and created a photo gallery for the iPhone. Now I want to add it to my TabBar project. I already heard, that Three20 doesn't support XIB, so I changed my whole tab bar setup to programmatically. I think I am not too far from a final solution.

I was able to get the photo gallery working in one tab but without functions (click on a pic --> it opens, etc). There is no navigation on top of the page that leads you to the detail image page. I faced this when I removed this from didFinishLaunchingWithOptions-method in app delegate:

// Override point for customization after application launch
TTNavigator* navigator = [TTNavigator navigator];
TTURLMap* map = navigator.URLMap;
[map from:@"demo://album" toViewController:  [AlbumController class]];

[navigator openURLAction:[TTURLAction actionWithURLPath:@"demo://album"]];
return YES;

I had to remove it because otherwise the whole tab bar is not shown. The photo gallery uses the whole screen. I am not sure if it is just not shown, or not loaded. I also tried:

tabbar.hidesBottomBarWhenPushed = NO;

But that did not work at all. I tried to add the TTNavigator-code to loadView(), viewDidLoad() and init() in the AlbumController itself without a result. Does anyone know where I have to put this in order to get it working?

My AlbumController.h:

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

@interface AlbumController : TTThumbsViewController {
    // images
    NSMutableArray *images;

    // parser
    NSXMLParser * rssParser;
    NSMutableArray * stories;
    NSMutableDictionary * item;
    NSString * currentElement;
    NSMutableString * currentImage;
    NSMutableString * currentCaption;
}

@property (nonatomic, retain) NSMutableArray *images;

@end

And my implementation of the didFinishLaunchingWithOptions-method:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    // set up tab bar controller
    tabBarController = [[UITabBarController alloc] init];        
    albumController = [[AlbumController alloc] init];  
    firstViewController = [[FirstViewController alloc] init];  
    secondViewController = [[SecondViewController alloc] init];  
    firstViewController.delegateRef = self;
    tabBarController.viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, albumController, nil];  
    [window addSubview:tabBarController.view];                                             
    [window makeKeyAndVisible]; 

    // Override point for customization after application launch
    TTNavigator* navigator = [TTNavigator navigator];
    TTURLMap* map = navigator.URLMap;
    [map from:@"demo://album" toViewController:  [AlbumController class]];
    [navigator openURLAction:[TTURLAction actionWithURLPath:@"demo://album"]];
    return YES;
}

Thanks guys, Cheers, dooonot

回答1:

Ok guys, with help of Bryan I was able to get the photo gallery running in a tab bar application. I have seen so many people out there looking for this solution so I try to explain it as good as I can.

Seems like it is not possible to use Three20 with Interface Builder, so you have to set up your tab bar application manually. This is my Three20PhotoGalleryAppDelegate.h:

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "AlbumController.h"
#import "SecondViewController.h"
#import "FirstViewController.h"

@class TabBarAppViewController;
@class AlbumController;
@class SecondViewController;
@class FirstViewController;

@interface Three20PhotoGalleryAppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UITabBarController *tabBarController;
    AlbumController *albumController;
    FirstViewController *firstViewController;
    SecondViewController *secondViewController;

@private
    NSManagedObjectContext *managedObjectContext_;
    NSManagedObjectModel *managedObjectModel_;
    NSPersistentStoreCoordinator *persistentStoreCoordinator_;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) UITabBarController *tabBarController;
@property (nonatomic, retain) AlbumController *albumController;
@property (nonatomic, retain) SecondViewController *secondViewController;
@property (nonatomic, retain) FirstViewController *firstViewController;

@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (NSURL *)applicationDocumentsDirectory;
- (void)saveContext;

@end

Please make sure that you create a new UITabBarController as well as all your ViewControllers. Let's continue with my Three20PhotoGalleryAppDelegate.m:

#import "Three20PhotoGalleryAppDelegate.h"
#import "AlbumController.h"
#import "SecondViewController.h"
#import "FirstViewController.h"
#import <Three20/Three20.h>

@implementation Three20PhotoGalleryAppDelegate

@synthesize window;
@synthesize albumController;
@synthesize firstViewController;
@synthesize secondViewController;
@synthesize tabBarController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    // set up tab bar controller manually
    tabBarController = [[UITabBarController alloc] init];        
    albumController = [[AlbumController alloc] init];  
    firstViewController = [[FirstViewController alloc] init];  
    secondViewController = [[SecondViewController alloc] init];  

    /* This is the essential part of the solution. You have to add the albumController to a 
    new  navigation controller and init it as RootViewController*/
    UINavigationController* navController = [[[UINavigationController alloc] initWithRootViewController:albumController] autorelease];

    // now add all controllers to the tabBarController
    tabBarController.viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, navController, nil];    

    [window addSubview:tabBarController.view];                                             
    [window makeKeyAndVisible];  
}

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {
    TTOpenURL([URL absoluteString]);
    return YES;
}

- (void)dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
}

@end

Please note that you don't need the TTNavigator stuff from the tutorial. Now we have to get our photogallery some how. I built it up in AlbumController like in the tutorial. This is my AlbumController.h:

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

@interface AlbumController : TTThumbsViewController {

}

@property (nonatomic, retain) NSMutableArray *images;

@end

You can find the implementation of the AlbumController in the tutorial mentioned above. Now the AlbumController.m:

#import "AlbumController.h"
#import "PhotoSource.h"
#import "Photo.h"

@implementation AlbumController
@synthesize images;

- (id)init
{
    if (self = [super init]) 
    {
        // Initialization code
        self.title = @"Photo Gallery";
        self.hidesBottomBarWhenPushed=NO;
    }
    return self;
}


- (void)viewDidLoad {

    [self createPhotos]; // method to set up the photos array
    self.photoSource = [[PhotoSource alloc]
                        initWithType:PhotoSourceNormal
                        title:@"All in Vain"
                        photos:images
                        photos2:nil];
}

-(void)createPhotos {
    // your independent implementation
}

@end

As described in the problem description above, my photo gallery always used the full screen. This is bad because you cannot use your tab bar icons anymore. For this you have to add

self.hidesBottomBarWhenPushed=NO;

to your init() method like mentioned in the AlbumController-init-method above.

Sooo, that's pretty much it. I really hope someone can re-use my solution. Thanks again to Bryan.

Cheers guys, doonot

PS: I have created a project on github. You can download the sample app here.



回答2:

Try This:

tBarController = [[UITabBarController alloc] init];
 actionController = [[ActionController alloc] initWithNibName:nil bundle:nil];
    // Override point for customization after application launch.
    TTNavigator* navigator = [TTNavigator navigator];
 TTURLMap* map = navigator.URLMap;
 [map from:@"demo://album" toViewController:tBarController];
 [tBarController setViewControllers:
     [NSArray arrayWithObjects:actionController,nil]];
 [navigator openURLAction:[TTURLAction actionWithURLPath:@"demo://album"]];

 [self.window addSubview:tBarController.view];
 [self.window makeKeyAndVisible];

    return YES;


回答3:

You can use the TTNavigatorDemo sample to learn how to use it with Tab Bar Controllers.