Trouble popping a view within a tab bar and nab bar - objective-c

I have a UITabBarController, which is the second item in a UINavigationBarController. Within the UITabBarController are a couple of views, one of which is a UIViewController subclass called AccountViewController. Got that?
Login View Controller -> UIViewController + UITabBarController - > Account View Tab -> Button
I want to use a button - Logout - to pop back to the Login view. How would I do that?

Assuming you are creating the UITabBarController within one of the UIViewControllers which are part of the string of view controllers within the UINavigationController where you have done something similar to this:
UITabBarController *mytabs = [[UITabBarController alloc] init];
[self.view addSubview:mytabs.view];
mytabs.delegate = self; // This is key to getting back your UINavigationController
You can call this from within one of the UIViewControllers that are added to your mytabs.viewControllers array like so:
[[(UIViewController *)self.tabBarController.delegate navigationController] popViewControllerAnimated:YES];
You can also specify if you want it to go to a specific viewController index in the UINavigationController stack ( just in case your Login viewController isn't the next one down or the root view controller ).

Related

What is the design pattern for navigating between ViewControllers?

I currently have 1 storyboard which contains 2 view controllers: ViewController and TableViewController. The ViewController is the login view, and the TableViewController is the page that displays results (results view).
Currently, I did not create a segue from the login view to the results view. Instead, on the login view, after a user presses the login button and is authenticated, I programmatically push to the results view as follows.
XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController pushViewController:controller animated:YES];
Indeed, the results view shows, but there is a "< Back" button at the top left, which, if pressed, goes back to the login view.
So, my question are:
How do I get rid of the login view from the view stack? (so the back button on the results view does not show)
Is this "programmatic" way of navigating between views "bad"? Meaning, should I rely on the storyboard and segues instead? Should I navigate to a new storyboard (I've seen this question asked on SO, though I haven't visited it yet)?
I'm a newcomer, so any help is appreciated.
If you don't want to use the navigation stack, you have to use presentViewController instead of pushViewController
XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
[viewController1 presentViewController:controller animated:YES];//viewcontroller1 is current view controller
Never use the code below unless you want to have the navigationController stack in viewController you are showing
/*XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController pushViewController:controller animated:YES]; */
for more information on this difference between presentViewController and UINavigationController?
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html

How to access Tab View Controller from another View Controller

I'm having trouble accessing my view controllers under the tab bar controller. Here is what my storyboard looks like:
View Controller A (-> Page View Controller -> View Controller C
View Controller A -> Tab Bar Controller (MyTabBarController.h/.m) -> Navigation Controller (MyNavigationController.h/.m)-> View Controller B (TabViewController.h/.m)
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller D
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller E
From View Controller A I have an IBAction called loginButton that is connected to the Tab Bar Controller, and currently it looks like this:
- (IBAction)loginButton:(id)sender {
MyNavigationController *localNavigationController;
UIStoryboard * storyboard = self.storyboard;
MyTabBarController *tbc = [[MyTabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:1];
TabViewController *login = [storyboard instantiateViewControllerWithIdentifier: # "TabViewController"];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:login];
localNavigationController.delegate = self;
[localControllersArray addObject:localNavigationController];
tbc.viewControllers = localControllersArray;
tbc.delegate = self;
tbc.moreNavigationController.delegate = self;
tbc.selectedIndex = 0;
[self presentViewController:tbc animated:YES completion:^{
}];
}
I'm not able to get this displayed correctly. I am getting a bunch of warnings in this piece of code. and it is also not showing the different tab items in the bottom of the Tab Bar, even though I have put images/text on each tab.
So how do I display/access the view controllers inside the Tab Bar Controller correctly? (ie View Controllers C/D/E)?
The storyboard that you show in your question already contains the tab bar controller, navigation controller, and login controller properly hooked up to each other. Because of that, you shouldn't be instantiating a new tab bar controller or navigation controller in code -- they will be instantiated by the storyboard when you instantiate the tab bar controller. So, the only thing you need to do, is to give the tab bar controller in the storyboard an identifier, and do this (assume the identifier is called MyTabBarController):
- (IBAction)loginButton:(id)sender {
UITabBarController *tbc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyTabBarController"];
[self presentViewController:tbc animated:YES completion:nil];
}
You wouldn't even need this code if you control drag from the "Login" button to the tab bar controller, and choose "Modal". That will create a modal segue which will present the tab bar controller with no code at all.
If you just want to select another tab from the tabBar controller then use something like this:
UITabBarController *tabBar = (UITabBarController *)self.window.rootViewController;
[tabBar setSelectedIndex:3];
Note that if the tabBar controller is the initial view controller you can grab an instance of it it the applicationDidFinishLaunching method and store it in the AppDelegate. Then you'll be able to access it like this:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
Remember to import the AppDelegate.h
I recommand you to use a Singleton shared instance to share multiple informations form multiple controllers.
It's a good design Pattern for you usage.
I'm writing samples of Design Patterns usage on cocoa (see https://github.com/leverdeterre/DesignPatterns -> Real singleton)

How to presentModalViewController without dismiss the TabBarController

Hey guys i`m trying to present a modal view controller inside an application with a tab bar controller. The problem is, every time the new view is presented, it on top of my tab bar.
I need to keep my tab bar even when the view is presented. Like google maps application does with his toolbar at the bottom of the screen.
How can i do that?
Thank you
By default, a modal view controller is meant to take up the entire screen (on an iPhone/iPod, at least). Because of this, it covers whatever you have on screen at the time.
A view controller presented via modal segue is meant to live on its own. If you want to keep your Navigation and TabBar, then just use a push segue to present the new ViewController. Remember to use this kind of segue, your presenting controller needs to be part of a UINavigationController already.
Use this to push a ViewController. If it is a UINavigationController it will push its linked RootViewController by itsself.
Create a viewController to push: (Using Storyboard)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
or (Using Code/Nibs)
LoginViewController *viewController = [[LoginViewController alloc] init]; //initWithNibNamed in case you are using nibs.
//in case you want to start a new Navigation: UINavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
and push with:
[self.navigationController pushViewController:vc animated:true];
Also, if you are using Storyboards for the segues you can use this to do all the stuff. Remember to set the segue identifier.
[self performSegueWithIdentifier:#"pushLoginViewController" sender:self]; //Segue needs to exist and to be linked with the performing controller. Only use this if you need to trigger the segue with coder rather than an interface object.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"pushLiftDetail"]) {
[[segue.destinationViewController someMethod:]];
segue.destinationViewController.someProperty = x;
}
}
I think you'll need to add a UITabBar to the modal view and implement/duplicate the buttons and functionality that your main bar has. The essence of a modal window is it has total control until it is dismissed.
You might try putting your UITabBarController into a NavBarController, but I'm not certain that this will work.
UITabBarController -> NavBarController -> Modal View

Switch views - UIViewController to UITabBarController

I have made a very simple Navigation based app (UIViewController). The view has a single button on the Main RootViewController.
Next, I made 2 classes: TabOneViewController, TabTwoViewController. All good. I then created a new Class TabBarViewController. I opened up the NIB file and dropped on a ``UITabBarController onto it. The two tabs it creates in it by default were assigned (respectively) to my TabOne and TabTwo view controllers.
strong text
Then in my TabBarViewController, I made an IBOutlet for a UITabBarController, synthesized it etc etc. I linked it up in Interface builder via the "files owner".
In the RootViewController, I linked the button to my "pushView" method, and in this pushView method, I have the following code:
- (IBAction) pushView {
TabBarViewController *controller = [[TabBarViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
The end result is it DOES push a view, but I cannot see the tab bar at the bottom, let alone any of the pages I've added to the controller.
What am I doing wrong? Why can't I link it in IB?
I am not 100% sure if that's allowed.. because you already have one tabBarController as rootViewController, and you dropped one more tabBarController as first tab controller, tabs ll overlap, considering amount of real estate you have on your iPhone, it make sense to not allow a tabViewController inside another
First, you need to allocate your view controller with your nib:
TabBarViewController *controller = [[TabBarViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
Secondly, in IB, click the UITabBarController and go to the identity inspector and make sure you select your custom class. That said, unless you are overriding or adding some functionality you probably don't need the custom class at all, simply use a UITabBarController directly:
UITabBarController *controller = [[UITabBarController alloc] initWithNibName:#"YourNibName" bundle:nil];

How to switch page on UINavigationBar on iPhone

I want to ask a question about the UI item on the UINavigationBar on the iPhone application. Im my program, there are a navigation bar and UITableView, like the following structure.
UIView (DataRootViewController.m)
|
+- UINavigationBar
|
+- UITableView
And, I want the it display the detail of the data when the user press one of the cell on the UITableView.
However, I don't know what should I do. I just create a class with UIViewController type (called DataDetailViewController.m) and leave it empty. What should I do for the next step? Which UI element should I add on the navigation bar in the detail view in order to let the user to go back to the basic page.
thank you very much.
You should be using a UINavigationController instead of trying to replicate the behavior. On your app delegate, try something like this.
RootViewController *rootViewController = [[RootViewController alloc] init];
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[window addSubview:[self.tabBarController view]];
Now, this RootViewController should have a table view, and when a user taps the table you should build your detail view controller and use
[[self.navigationController] pushViewController:myDetailViewController animated:(BOOL)animated];