Switching between two UITabBarController? - ios

I'm developing storyboard based app and I'm wondering if I could have 2 TabBarControllers - one is for user not logged in and another one for user logged in. Can I swap NotLoggedInTabBarController to LoggedInTabBarController on login button action?

If you add a Restoration ID to your viewControllers in the storyboard (identity inspector) you can instantiate a controller by calling the method instantiateViewControllerWithIdentifier:
In your case, maybe i would have instantiate a parent view controller, and when wanting to swap of tabBarcontroller, I would have called
[parentViewController.storyboard instantiateViewControllerWithIdentifier:#"tabBarController2"];
And then change controller displayed.
(Not tested, just some ideas...)

You can add IBAction to your button with check of this condition and instantiate needed controller.
ViewController *viewController = nil;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
YourViewController *viewController = nil;
if ([userManager isLoggedIn]) {
viewController = (YourViewController *)[storyboard instantiateViewControllerWithIdentifier:#"LoggedInViewControllerIdentifier"];
} else {
viewController = (YourViewController *)[storyboard instantiateViewControllerWithIdentifier:#"NotLoggedInViewControllerIdentifier"];
}
[self.navigationController pushViewController:viewController animated:YES];
in your storyboard you'll have to set storyboard id in Identity inspector
EDIT
If you are not using navigationController to route to correct logged/notlogged controllers then your could do sth like that:
MyAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate.transitionController transitionToViewController:viewController
withOptions:UIViewAnimationOptionTransitionFlipFromRight];

Related

How to pass value to a viewController embedded in NavigationController

There are similar questions but they are either in swift or are not solving my problem.I've a view controller which is presenting navigation view controller when cell did select button is pressed as:
patientBillNavigationViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PatientBillVC"];
//soem value assignment
[self presentViewController:viewController animated:YES completion:nil];
You can say billing opens up a whole new view independent of the main app flow to handle billing process.
The view this navigation View Controller automatically loads is the bill view and now if I want to pass a value from this viewcontroller to the other viewController embedded in navigation view I can't do that. How to pass a value?
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
PatientBillViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"PBVC"];
vc.superBillToAddEdit = sb;
//then display the view embedded in navigation view
But this is not working.
One way I know is to Subclass UINavigationViewController and in its viewDidLoad, you can do:
YourEmbeddedVc *svc =self.viewControllers[0]; //get the controller reference
svc.name= #"Hello";
I'm assuming you are only having one controller in your navigation stack, if not you need to find out the proper match of the required VC.
I might not be understanding the question exactly, correct me if I'm wrong.
It sounds like you want to start a nav controller from a view controller (let's call this firstViewController) and pass a value from firstViewController to the view controller that will eventually load in the nav controller.
If that's the case, why don't you create the second view controller (billingStep1ViewController) and then assign the value to it as a property, then pass the billingStep1ViewController to the nav controller's initWithRootViewController: method?
Something like this (untested code, btw):
// this code would go inside our FirstViewController file
// create the first vc that will be loaded in the nav controller
BillingStep1ViewController *billingStepOneVc = [self.storyboard instantiateViewControllerWithIdentifier:#"stepOne"];
// set the value you want
billingStepOneVc.bill = myBill;
// create new nav controller with step one vc as the root
UINavigationController *uiNavController = [[UINavigationController alloc] initWithRootViewController:billingStepOneVc];
[self presentViewController:uiNavController];
That way you can have two view controllers talking directly with one another and not worry about the navigation controller at all.
Update: Here is some tested code that works to illustrate my idea:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
//create the step 1 view controller - this is the first view controller we will see in the navigation controller
StepOneViewController *stepOneVc = [storyboard instantiateViewControllerWithIdentifier:#"stepOne"];
//assign a value to it (name is an NSString #property of StepOneViewController)
stepOneVc.name = #"Jones";
//this is the nav controller we will display, we set the root vc to our step one.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:stepOneVc];
//present the nav controller on screen.
[self presentViewController:navController animated:YES completion:nil];
Some of the class names changed but the idea is the same.
Rather than creating the navigation controller from its storyboard identifier, create it programmatically, with the PatientBillViewController you created as its root view controller. Like this:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
PatientBillViewController *pbVC = [mainStoryboard instantiateViewControllerWithIdentifier:#"PBVC"];
pbVC.superBillToAddEdit = sb;
PatientBillNavigationViewController * navVC = [[PatientBillNavigationViewController alloc] initWithRootViewController:pbVC];
[self presentViewController:navVC animated:true completion:nil];
Swift Version
Here is the swift version answer for the above problem!!
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PatientBillVC") as! patientBillNavigationViewController
vc.name = "name"
let mVc = UINavigationController.init(rootViewController: vc)
self.navigationController?.present(mVc, animated: true, completion: nil)

How to navigate to a view controller on a new storyboard file in objective-c

I got a source code for an existing app. throughout the app the developer didn't use storyboard for the user interface but rather he used interface builder xib files. As a new developer, i don't know how to develop iOS apps in xcode using xib files for viewcontrollers, i learnt the storyboard way. Now I want to add more screens to the apps source code, i created a new storyboard file to define my new screens, how do I navigate to the entry point of this new storyboard from a button action i defined in one of the xib files so that i can easily implement my features.
while searching i got some suggestions like this one
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"newStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"myViewCont"];
but i dont think i understand how to implement this even if this can be in a button IBAction method. and besides subsequent navigations would be segues through the view controllers i define in the new storyboard
It's right suggestion.
You should get storyboard object by its name. Then you should create your viewController using [storyboard instantiateViewControllerWithIdentifier:#"..."];
Then you may navigate to your new VC using appropriate navigation method. For example:
[self.navigationController pushViewController:vc animated:YES]
ViewController identifier you should set in Interface Builder under section "Identity Inspector" in field "Storyboard ID".
That code you should place in IBAction method. But better would be to extract it in separate method. Something like this:
- (IBAction)buttonPressed:(UIButton *)sender {
[self navigateToMyNewViewController];
}
- (void)navigateToMyNewViewController {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"myNewStoryboard" bundle:nil];
MyNewViewController *myNewVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"MyNewViewController"];
[self.navigationController pushViewController:myNewVC animated:YES];
}
Navigation from MyNewViewController your can implement as you want. It may be segues.
MyNewViewController *myVC = [self.storyboard instantiateViewControllerWithIdentifier:#"YOUR_VC_NAME_HERE"];
This will instantiate your ViewController, from here you can present it like so
[self presentViewController:myVC animated:YES completion:nil]
The image shows where you set the storyboard name that you're referring to
Try This it's working for me ,
Use below line of code :
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main"bundle:nil];
LoginViewController *loginVC = (LoginViewController*)[storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self.navigationController pushViewController:loginVC animated:YES];
We need to set storyboard id as per mention in below,
you can navigate one storyboard to another storybord:
first you import your viewcontroller class to appdelegate.h
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
appDelegateTemp.window.rootViewController = [[UIStoryboard storyboardWithName:#"storyboard_name" bundle:[NSBundle mainBundle]] instantiateInitialViewController];
Like the way you use storyboard, use
MainViewController *mainVC = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil]
[self.navigationController pushViewController:mainVC animated:YES];

How to open new view controller after click button?

I added one ViewController to my project and created one class.
After I bind this class to my ViewController.
In another controller I have method:
- (IBAction)login:(id)sender {
// How here I can do redirect to controllerViewController
}
There are two ways to push view controllers in the application.
1) by Segue
2) By View controller identifier
1) By Segue :
[self performSegueWithIdentifier:"SegueIdentifier" sender:self];
2) By View controller identifier :
Yourclassname *gotoYourClass = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewControllerIdentifier"];
[self.navigationController pushViewController:gotoYourClass animated:YES];
- (IBAction)login:(id)sender {
ViewController *vc = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self presentViewController:vc animated:YES completion:nil]; }
In the storyboard give your view controller an identifier (under the Attributes Inspector) then use the following code, to bring that view forward.
IF YOU WANT TO USE PUSH THEN USE THIS CODE
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"VIEWCONTROLLERIDENTIFIER"];
[self.navigationController pushViewController:vc animeted:YES];
IF YOU WANT TO PRESENT THEN USE THIS CODE
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"VIEWCONTROLLERIDENTIFIER"];
[self presentModalViewController:vc animated:YES];
Note: In UIViewController please enter your view controller name which you want to push into another view.
If you want to comeback to the current ViewController later then use Navigation ViewController or else just use the presentedViewController of self(your current viewController)- no going back business, like they have previously illustrated.
For a simple block of execution(demo or practice) it's all the same but for a project application it completely matters to make the correct choice.

properly set up navigation controller as a root for a uitab bar

I am a little bit confused and cannot make things to work.
So, this is my code in my app Delegate.
// If the device is an iPad, we make it taller.
_tabBarController = [[AKTabBarController alloc] initWithTabBarHeight:(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 70 : 50];
NSString * storyboardName = #"Main_iPhone";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
CurrentViewController * tab1VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
// dummy controllers
CurrentViewController * tab2VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
CurrentViewController * tab3VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
CurrentViewController * tab4VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
[_tabBarController setViewControllers:[NSMutableArray arrayWithObjects:
tab1VC,
tab2VC,
tab3VC,
tab4VC,
nil]];
[_window setRootViewController:_tabBarController];
[_window makeKeyAndVisible];
Then, in my storyboard I have the image below :
So, I have my ViewController and I clicked Embed In > Navigation Controller
I want to have a different navigation controller for each tab.
Inside my CurrentViewController I have this when button is clicked :
- (IBAction)dummyButton:(id)sender {
NSString * storyboardName = #"Main_iPhone";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UserSettingsSetupViewController *userSettingsSetupController = [storyboard instantiateViewControllerWithIdentifier:#"UserSettingsSetup"];
[[self navigationController] pushViewController:userSettingsSetupController animated:YES];
}
And apparently nothing is pushed into the navigation Controller because nothing opens.
Doing some research, I saw that this is because [self navigationController] or self.navigationController returns nil.
but why is that? Should I add any code? I thought that by doing that from storyboard, it shouldn't be nil? Am I wrong?
A couple of comments. First of all, if you're using a storyboard, don't create view controllers in the app delegate; drag all the controllers you need into the storyboard. There's no need for any added code in the app delegate at all.
Your problem is caused by trying to mix storyboard controllers and code in the app delegate. You are instantiating tab1VC and making that the controller in the first tab -- that controller doesn't "know" anything about the navigation controller you added in the storyboard. If you wanted to do it in code (which I don't recommend), you would need to instantiate that navigation controller instead (it will take care of instantiating its root view controller), and add that as the first item in the viewControllers array.
My advice is do it all in the storyboard. Change the class of the tab bar controller there to AKTabBarController, and set its tab bar height in its init method or viewDidLoad.

How do I segue from a NIB subview to a viewcontroller in the storyboard

I have a combination of a storyboard and NIB viewcontrollers how can I segue from one to the other
This is the Scenario:
UITabBarController(storyboard)|- UINavigationController (subclassed in storyboard) -> [UIViewController (NIB)] -> UIViewController (in Storyboard)
You'll have to give the UIViewController in the Storyboard a 'Storyboard ID' (in the Identity inspector tab). Then instantiate that ViewController in your NIB ViewController's code like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"YourViewControllerId"];
[self.navigationController pushViewController:vc animated:YES];
In your UINavigationController subclass you need to instantiate your view controller with its view in a NIB(let's call it NIBViewController) and set that view controller as the rootViewController with the method setViewControllers:animated:. Do it in awakeFromNib like this:
- (void)awakeFromNib
{
[super awakeFromNib];
NIBViewController *viewController = [[NIBViewController] init];// It will look for the appropriate XIB as long as you did not change its name and it's in the main bundle, otherwise use initWithNibName:bundle:
[self setViewControllers:#[viewController] animated:NO];
}
Then, to go from the NIBViewController to other view controller contained in the storyboard just set an identifier in the storyboard for that view controller, instantiate it and push it or present it, as you want.
It is important to mark that in your NIBViewController instance self.storyboard will be nil because that view controller is not contained in a storyboard, so you need to instantiate a new storyboard(solution A**) or get the storyboard from the navigation controller(solution B):
// Solution A
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
// Solution B
UIStoryboard *storyboard = [self.navigationController storyboard];
UIViewController *storyboardViewController = [storyboard instantiateViewControllerWithIdentifier:#"viewControllerId"];
[self.navigationController pushViewController:storyboardViewController animated:YES];
** Please note that this is creating a new instance of the storyboard, so better not to try tricky things and avoid segues to previous view controllers contained in the storyboard or you will find that those view controllers are not the same ones... It's the first solution that came to my mind, but definitely you should go for the solution B.

Resources