I have programatically created a TabBarController with views etc. Now i want to show this TabBarController on Button Press. How do i do that? Currently i am presenting it modally but it doesn't work - throws sigtrap errors.
This is my code for the TabBarController
#implementation TabBarViewController
- (void) loadView
{
HomeViewController * homeViewController = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.view.frame = CGRectMake(0, 0, 320, 460);
// Set each tab to show an appropriate view controller
[tabBarController setViewControllers:[NSArray arrayWithObjects:homeViewController, homeViewController, nil]];
[self.view addSubview:tabBarController.view];
[homeViewController release];
[tabBarController release];
}
This is my code for accessing this tabBarController from a Button Press event from my mainViewController -
- (IBAction)quickBrowse:(UIButton *)sender
{
TabBarViewController * tabBarController = [[TabBarViewController alloc]init];
[self presentModalViewController:tabBarController animated:YES];
[tabBarController release];
}
You should only override the method loadView if you are not using IB and if you want to create yours view manually. And when you do that you must assign your root view to the view property of UIViewController.
I believe in your case you don't need to override this method, you can use the viewDidLoad method to create your UITabBarController and store it in a variable, so when the event gets called all you need to do is pass the variable to the method presentModalViewController:animated:
Your final code would look like this:
- (void) viewDidLoad
{
[super viewDidLoad];
HomeViewController * homeViewController = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
// you can't pass the same view controller to more than one position in UITabBarController
HomeViewController * homeViewController2 = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
// local variable
self.modalTabBarController = [[UITabBarController alloc] init];
// Set each tab to show an appropriate view controller
[self.modalTabBarController setViewControllers:[NSArray arrayWithObjects:homeViewController, homeViewController2, nil]];
}
- (void)viewDidUnload
{
self.modalTabBarController = nil;
[super viewDidUnload];
}
- (IBAction)quickBrowse:(UIButton *)sender
{
[self presentModalViewController:self.modalTabBarController animated:YES];
}
Related
I have three tab bar application and my tabs is TAB1, TAB2 , TAB3 i have write the following code in TAB1 view controller to detect which tab user have pressed
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
NSLog(#"tab selected: %#", item.title);
}
But this delegate never get called
i have setup my tab in appdelegate.m something like that
- (void)setupTabBar
{
self.myWorkListViewController = [[MyWorkListViewController alloc] initWithNibName:#"MyWorkListViewController"
bundle:nil];
self.askHRViewController = [[AskHRViewController alloc] initWithNibName:#"AskHRViewController"
bundle:nil];
self.moreViewController = [[MoreViewController alloc] initWithNibName:#"MoreViewController"
bundle:nil];
self.bookLeaveViewController = [[BookLeaveViewController alloc] initWithNibName:#"BookLeaveViewController"
bundle:nil];
self.helpViewController = [[HelpViewController alloc] initWithNibName:#"HelpViewController"
bundle:nil];
// Create navigation controllers
workListNavigationController = [[UINavigationController alloc] initWithRootViewController:self.myWorkListViewController];
askHRNavigationController = [[UINavigationController alloc] initWithRootViewController:self.askHRViewController];
bookLeaveViewController = [[UINavigationController alloc] initWithRootViewController:self.bookLeaveViewController];
moreNavigationController = [[UINavigationController alloc] initWithRootViewController:self.moreViewController];
helpNavigationController = [[UINavigationController alloc] initWithRootViewController:self.helpViewController];
[self setTabBarImagesAndText];
// Setup tab bar controller
self.tabBarController = [[UITabBarController alloc] init];
[self.tabBarController setViewControllers:[NSArray arrayWithObjects:workListNavigationController, askHRNavigationController, bookLeaveViewController, helpNavigationController,moreNavigationController, nil]];
//Set TabBar background
[self.tabBarController.tabBar insertSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"TabBar_iOS4_Background"]] atIndex:0];
[self.tabBarController setSelectedIndex:0];
}
you can detect selected Tabbar Item like this way:-
as par your code you just need to add this line
// Setup tab bar controller
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate=self;
[self.tabBarController setViewControllers:[NSArray arrayWithObjects:workListNavigationController, askHRNavigationController, bookLeaveViewController, helpNavigationController,moreNavigationController, nil]];
//Set TabBar background
[self.tabBarController.tabBar insertSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"TabBar_iOS4_Background"]] atIndex:0];
[self.tabBarController setSelectedIndex:0];
in .h file define like
#interface yourViewcontroller : UIViewController<UITabBarControllerDelegate>
{
//declare your Tabbar controller with #proparty
}
in .m file
//#synthesize here your Tabbar controller
- (void)viewDidLoad
{
self.yourTabbarControler.delegate=self;
[super viewDidLoad];
}
and now put this delegate of UITabbarController
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController
{
NSLog(#"controller class: %#", NSStringFromClass([viewController class]));
NSLog(#"controller title: %#", viewController.title);
if (viewController == tabBarController.moreNavigationController)
{
tabBarController.moreNavigationController.delegate = self;
}
}
You have to "wire up" the delegate, either using code (in ViewDidLoad etc.) or in interface builder.
Look at this answer which explains how to connect a textView delegate (it's pretty much the same): https://stackoverflow.com/a/1785366/764575
I'd like to add a UINavigationController to my app info view (NOT to my main view). I've watched/read a number of tutorials showing how to add it to the main window through the AppDelegate using IB. In my case, I only want it to appear when a user presses the info button and is brought to the infoView. Here is how I switch to the infoView within my MainViewController:
- (IBAction)infoButtonPress:(id)sender
{
// Create pointer to instance of InfoViewController
InfoViewController *infoView = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle:nil];
// Add view switching animation
infoView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
// Change view using animation
[self presentModalViewController:infoView animated:YES];
}
At this point the infoView is displayed and I would like THIS to be the RootView of the UINavigationController. I have tried adding the line:
UINavigationController *infoNavController = [[UINavigationController alloc]
initWithRootViewController:infoView];
after creating an instance of InfoViewController, but the app crashes. Is it possible to add UINavigationController to views other than the main view?
Thanks.
You are very close with your implementation. Try it in this order.
InfoViewController *infoView = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle:nil];
UINavigationController *infoNavController = [[UINavigationController alloc]
initWithRootViewController:infoView];
[infoView release]; // skip this if using ARC
infoView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:infoNavController animated:YES];
UPDATE
To kill this modal, you will have to add your buttons to the main modal view.
InfoViewController.m
-(void)cancel:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
-(void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *cancelButton =
[[UIBarButtonItem alloc] initWithTitle: #"Cancel"
style: UIBarButtonItemStylePlain
target: self
action: #selector(cancel:)];
self.navigationItem.leftBarButtonItem = cancelButton;
[cancelButton release];
}
This is a view based application.
in delegate.m file I have done like this to launch login screen initially:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
[window addSubview:viewController.view];
[window makeKeyAndVisible];
LoginView *loginView=[[LoginView alloc]initWithNibName:#"LoginView" bundle:nil];
[window addSubview:loginView.view];
}
By adding the above code I have launched login screen sucessfully, but at the bottom of my login screen I can see a space left out.
How can the tab bar controller get launched after sucessful login?
i have creatd a method called login in my LoginView.m file:
-(void)login
{
if(login)
{
TabBarController *tabBarController = [[TabBarController alloc] initWithNibName:#"TabBarController" bundle:nil];
[self.view addSubView: aTabBarController.view];
}
[aTabBarController release];
Please help me out of this with the appropriate code.
you have to create on method in appDelegate like.. and In appDelegate.h you have to create an object like this
UITabBarController *Obj_tabbar;
and then in .m file,
-(void) switchToTabbarController
{
Obj_tabbar.delegate = self;
Obj_tabbar.selectedIndex = 0;
Tracking_HomeVC *obj = [[Tracking_HomeVC alloc]init];
[self tabBarController:Obj_tabbar didSelectViewController:obj];
[self.window addSubview:Obj_tabbar.view];
}
// At this point Tracking_HomeVC is the first view controller of the TabbarController. and it will be added on window.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([tabBarController selectedIndex] == 0)
{
//Write your code here to do with the first view controller object.
}
}
and then call it from your LoginView like..
-(void)LoginPressed
{
AppAppDelegate *delegate =(AppAppDelegate *) [[UIApplication sharedApplication] delegate];
[delegate switchToTabbarController];
}
Your login view (or it's controller if you have one which it looks like you don't) should tell the appDelegate to swap the RootViewController to be a taBarController. You do NOT want the loginview to be trying to add a tabBar as a child of itself.
One way of doing it is creating a tabbarcontroller like normal in your appdelegate and set it as rootviewcontroller:
TOTabBarController *tabBarController = [[TOTabBarController alloc] init];
UIViewController *vc1 = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UIViewController *vc2 = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UIViewController *vc3 = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *vc2_nc = [[UINavigationController alloc] initWithRootViewController:vc2];
UINavigationController *vc3_nc = [[UINavigationController alloc] initWithRootViewController:vc3];
NSArray *viewControllers = [NSArray arrayWithObjects:vc1, vc2_nc, vc3_nc, nil];
[tabBarController setViewControllers:viewControllers];
//set tabbarcontroller as rootviewcontroller
[[self window] setRootViewController:tabBarController];
Then display the login screen modally (without animation) if the user is not logged in:
if (not logged in) {
UIViewController *lvc_nc = [[UIViewController alloc] init];
[[[self window] rootViewController] presentModalViewController:lvc_nc animated:NO];
}
Hope that helps!
I am building an app that has a login screen that leads to a tabbar. I followed this example on how to push a modal view once you launch the app (as the "sign in" page) and then dismiss it.
Example --> Show / Hide tab bar
From some reason, it's not really working - when I launch the app, I see the tabbar view with the two view controllers. no sign in page.
here is my code:
AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1 = [[FirstTab alloc] initWithNibName:#"FirstTab" bundle:NSBundle.mainBundle];
UIViewController *viewController2 = [[SecondTab alloc] initWithNibName:#"SecondTab" bundle:NSBundle.mainBundle];
UINavigationController *secondNavController = [[UINavigationController alloc]initWithRootViewController:viewController2];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, secondNavController, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
My first tab (which is where I understand all this modal view business needs to happen)
.h
#interface FirstTab : UIViewController
#end
.m
//UPDATED CODE PER COMMENT BELOW
- (void)viewDidLoad
{
[super viewDidLoad];
SignIn *loginview = [[SignIn alloc] initWithNibName:#"SignIn" bundle:nil];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController: loginview];
self.hidesBottomBarWhenPushed = YES;
[self presentModalViewController:controller animated:YES];
}
And of course, I dismiss the modal view in the SignIn view controller, though I never get there as I mentioned.
What am I doing wrong here? Thanks for the help!!
You could use :
[[self tabBarController] presentModalViewController:controller animated:YES];
since first viewController1 is your first tab, and self.navigationController might be nil.
In your custom view controller subclass called SignIn implement initWithNibName:bundle: instead if init.
-(id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// init here
}
}
Now when init/alloc it call either :
SignIn *loginview = [[SignIn alloc] initWithNibName:#"SignIn" bundle:nil];
if your interface is in a NIB file, or :
SignIn *loginview = [[SignIn alloc] initWithNibName:nil bundle:nil];
if there no NIB.
Also why putting it as a root view controller of any navigation controller ? unless you need to go deeper in some model data presentation, just present it directly :
// why ?
//UINavigationController *controller = [[UINavigationController alloc]
// initWithRootViewController: loginview];
//self.hidesBottomBarWhenPushed = YES;
//[self presentModalViewController:controller animated:YES];
[self presentModalViewController:loginView animated:YES];
You have to include this in your code,
yourModelController =[[Yourmodelcontroller alloc]init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController: yourModelController];
self.hidesBottomBarWhenPushed = YES;
[[self navigationController] presentModalViewController:controller animated:YES];
[controller release];
hope this will help you out.
I've encountered issues where modals don't like showing from viewDidLoad. Try adding your code to your viewWillAppear and it should show.
I have a controllerView (MenuControllerView) with a button inside, when I click on the button a new ViewController will appear with a TabBarController created programmatically like this:
UIView* topView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
tabBarController = [[UITabBarController alloc] init];
viewController1 = [[ViewController1 alloc] init];
viewController2 = [[ViewController2 alloc] init];
viewController3 = [[ViewController3 alloc] init];
viewController4 = [[ViewController4 alloc] init];
tabBarController,viewControllers = [NSArray arrayWithObjects:viewController1 , viewController2 , viewController3 ,viewController4, nil];
[[self tabBarController] setSelectedIndex:1];
[topView addSubView:[tabBarController view]];
Instead of displaying ViewController1 for the first button Item, I want to put an action Back in it to return to my MenuViewController, but I don't know how how to do it.
Thanks
Have you considered presenting the UITabBarController as a modal view controller and implementing UITabBarControllerDelegate? e.g. this seems to work for me (I make the third tab return to MenuViewController here):
#interface MenuViewController : UIViewController <UITabBarControllerDelegate>
...
- (IBAction) onButtonPressed:(id)sender
{
UITabBarController* tabBarController = [[UITabBarController alloc] init];
viewController1 = [[ViewController1 alloc] init];
viewController2 = [[ViewController2 alloc] init];
viewController3 = [[ViewController3 alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1 , viewController2 , viewController3 , nil];
[[self tabBarController] setSelectedIndex:1];
tabBarController.delegate = self;
[self presentModalViewController:tabBarController animated:NO];
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
{
if (viewController == viewController3)
{
[self dismissModalViewControllerAnimated:NO];
return NO;
}
return YES;
}
I doubt that this approach is a good one. You'll gonna break typical iPhone behaviour which will confuse users. The TabBarController is designed (functionally and technically) to change between views while a NavigationController is for pushing and popping views (go forth and back). Of course you can combine those (which is not always easy), but you shouldn't use TabBar as NavigationBar.
if I understand right, you can just remove your tabbar's view from superview. smth like
[[tabBarController view] removeFromSuperview];
if you just want to handle selection of tabbar item, you can use tabBar:didSelectItem: method of th UITabBarDelegate protocol.
Is this what you're trying to do?
This automatically created with a UINavigationController upon pushing to a child view controller.
[self.navigationController pushViewController:yourChildViewController animated:YES];