So I have a navigation controller leading to a table view, which leads to a detail view. There is an add button leading to another table view to choose from a contacts list. When I select DONE, I want to lead to a new detail view, but the navigation bar won't display. Below is an image of the IB:
So I want to move from the Contacts View Controller to the Convo View Controller but keep the navigation item working.
The code that is executed when the DONE button is pressed:
- (IBAction)doneButtonPressed:(UIBarButtonItem *)sender {
BOOL sharing = NO;
if ([self.referrer isEqualToString:#"mapView"]) sharing = YES;
Convo *newConvo = [[Convo alloc] initWithMembers:self.selectedContacts
sharing:sharing];
// add newConvo to convos list
ConvoViewController *convoVC = [self.storyboard
instantiateViewControllerWithIdentifier:#"convoView"];
convoVC.convo = newConvo;
NSLog(#"%#", [convoVC.convo memberListToString]);
[self presentViewController:convoVC
animated:YES
completion:nil];
}
Thank you for any help!
I would do what you're trying to do, by embedding the ContactsViewController in its own navigation controller, and segueing (from the Done button) to the new instance of ConvoViewController (the one with the title of "Contacts Detail"). In that controller I have a bar button item called "Main Table" that's connected to an unwind segue that unwinds back to MasterViewController. Here is the setup,
Related
I have the following in Interface Builder:
The top left is my main view controller where I have 2 buttons that have segue to two UIViewControllers. These two UIViewControllers are linked with the Tab Bar Controller. However, how could I make those 2 buttons to link to specifically to one/other views? Right now it's connected specifically, but it (or something else) causes the bar tab not show up.
Is it the problem that I don't have the Tab Bar Controller connected to the main view?
Yes, you're right that the problem occurs because the tab bar controller needs to be the destination of the segues. Fix it like this:
In IB, erase the segues from the two buttons and create two new ones, one from each button to the tab bar controller. Give each one an identifier, like buttonA from one button and buttonB from the other.
In the view controller, implement prepareForSegue for each segue understanding that the destination is a tab bar controller and that each segue requires a different tab selection...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"buttonA"]) {
UITabBarController *tabBarController = (UITabBarController *)segue.destinationViewController;
tabBarController.selectedIndex = 0;
}
if ([segue.identifier isEqualToString:#"buttonB"]) {
UITabBarController *tabBarController = (UITabBarController *)segue.destinationViewController;
tabBarController.selectedIndex = 1;
}
}
That's not quite how the tabBarController works.
I can see your initial view controller is the one on the top left, and it pushes either of the other two on the right on to the navigation stack if you push a button. But in your current setup, at no point does the tab controller itself get pushed on to the stack.
Instead, you would want to have your initial view controller push the tab bar controller on to the stack, through a button or otherwise, and the tab bar controller will display your other two view controllers as its setup to do.
I am developing one i pad application using story board.In my storyboard i have tab bar controller and another 4 view controllers are connected to tab bar controller are tab items.I have one button in the first view controller.If i click that button i need to display 4th view controller.If i give a direct segue from first view controller to 4th view controller using
[self performSegueWithIdentifier:#"SegueIdentifier" sender:nil];
the 4th view controller is appeared but the tab bar display at the bottom is disappear.
You need to do something like this when the button is pressed...
[self.tabBarController setSelectedIndex:3];
This will tell the tab bar controller to change the selected tab.
Try use it->
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"SegueIdentifier"]) {
[self.tabBarController setSelectedIndex:3];
}
}
I have a tab bar controller with 3 view controllers and one navigation view controller in it.
That navigation view controller has a table view controller and detail view.
In my first view controller (first tab) there are three buttons. I want the first button to load the detail view in the navigation controller. (as seen on image below)
Storyboard
How can i achieve this ?
I have tried calling the method that performs the segue in LocationsTableViewController, but that gives me the error "Receiver () has no segue with identifier 'addLocation'". Although a segue "addLocation" certainly exists.
Method connected to button in StartViewController:
- (IBAction)addLocationView:(id)sender {
LocationsTableViewController *LTVC = [[LocationsTableViewController alloc] init];
[LTVC addLocation];
}
LocationsTableViewController:
-(void)addLocation
{
[self performSegueWithIdentifier: #"addLocation" sender: self];
}
Your "addLocation" segue is from the Locations Table View Controller to the Add Location View Controller, so the segue exists on the LocationsTableViewController. That is correct. However, if your current view controller isn't LocationsTableViewController, it doesn't make sense to call that segue.
You have a few options:
Storyboard Option #1: Make a new segue from StartViewController to AddLocationViewController, and perform that segue in addLocationView:.
Storyboard Option #2: Make a new segue from the button to the AddLocationViewController, and remove your IBAction. The storyboard will automatically call that segue when the button is clicked.
Programatic Option: Instantiate a new AddLocationViewController and push it onto the navigation stack: [self.navigationController pushViewController:[[AddLocationViewController alloc] init] animated:YES].
I am developing an iOS application that uses a left side slide out drawer containing tabs, each representing one of the main views of the app. Currently, when the user selects a tab the application searches through the navigation stack for an instance of the relevant view controller and if it finds one pops back to that controller, otherwise it creates a new instance and pushes it onto the stack.
I would like to also add a back button allowing the user to go back to the previous view, however since many navigation options will pop the user to a previous view controller resulting in the controller they are leaving being dealloc'ed there is no obvious way to have a back button to get back to that controller again.
Is there any way to structure this application so that a back button can be added, while still allowing the user to use the tabs to navigate to any view at a given time?
An example of the navigation code follows (invoked when a user clicks one of the tabs):
if(![self.navigation.topViewController isKindOfClass:[GraphViewController class]]) { //Are we already in this view?
BOOL foundController = NO;
for(id controller in self.navigation.viewControllers) { //Is there a controller of this type already in the stack?
if([controller isKindOfClass:[GraphViewController class]]) {
[self.navigation popToViewController:controller animated:YES];
foundController = YES;
break;
}
}
if(!foundController) {
GraphViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"graphViewController"];
controller.connection = _connection;
controller.data = _dataCache;
[self.navigation pushViewController:controller animated:YES];
}
}
I believe what you want is navigation controllers for each item in the slide out menu. This way when the user selects a view from the side menu they can navigate the views associated with that section. This will allow the user to go back from a view once they have selected a item from the side menu.
I am using view controller containment, and as part of my implementation a child view controller needs to disable a bar button item of the navigation controller of the parent view controller. The theory is that being a child view controller, I had access to the same navigation controller (in my context anyway) as the parent view controller's.
From debugging I can see that self.navigationController and self.parentViewController.navigationController were set to the same address.
For example:
NSLog(#"%# - %#", self.navigationController,
self.parentViewController.navigationController);
NSLog(#"%# - %#", self.navigationItem,
self.parentViewController.navigationItem);
NSLog(#"%# - %#", self.navigationController.navigationItem,
self.parentViewController.navigationController.navigationItem);
Resulted in the following console log:
<UINavigationController: 0xc482290> - <UINavigationController: 0xc482290>
<UINavigationItem: 0xa5f3620> - <UINavigationItem: 0xc482490>
<UINavigationItem: 0xa5f36e0> - <UINavigationItem: 0xa5f36e0>
Results
Navigation controllers are the same, as expected (self->navController == self->parent->navController).
Navigation item's are different, this is expected. Each view controller has it's own nav item (self->navItem != self->parent->navItem).
Accessing the navigation controllers nav item from the parent or the child view controller is identical, as expected (self->navController->navItem == self->parent->navController->navItem)
So I now ask: why didn't disabling a bar button item in the child view controller with the following code work:
self.navigationController.navigationItem.rightBarButtonItem.enabled = NO;
This should be synonym to the following (which does work as expected) given their shared address:
self.parentViewController.navigationController.navigationItem.rightBarButtonItem.enabled = NO;
Update
I was reading my logs too fast. Indeed the parentViewController and the navigation controller have 2 different navigation items. I missed this in my example here because the memory addresses were extremely close: 0xa5f3620 != 0xa5f36e0
A UINavigationController has it's very own navigationItem (like any other UIViewController) that will only come into play if you push it onto the stack of another UINavigationController.
Generally you aren't going to push one UINavigationController onto another so manipulating self.navigationController.navigationItem is pointless.
EDIT:
To check ... I've just aded:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UINavigationItem *myNavControllersItem = self.navigationController.navigationItem;
UINavigationItem *myItem = self.navigationItem;
NSLog(#"%# - %#", myNavControllersItem, myItem);
}
to a VC that I'm pushing onto a NavController and get:
<UINavigationItem: 0x1ed0c170> - <UINavigationItem: 0x1ed46330>
Additionally, if I add:
self.navigationItem.rightBarButtonItem.enabled = NO; to viewDidAppear the right button gets disabled.
if I add:
self.navigationController.navigationItem.rightBarButtonItem.enabled = NO; it does not.
Well basically the problem is the way the navigation controller updates the bar button items, basically the buttons are update whenever the top-level child is changed.
For the right bar button item, if the new top-level child has it's own bar buttons items then the navigation controller will select the existing one, if not nothing will be displayed.
So in your case the parrentViewController already has a navigationItem.rightBarButonItem which is not disabled, by calling self.navigationController.navigationItem.rightBarButtonItem.enabled = NO; you are disabling the child's nabigationItem.rightBarButtonItem and you can't see this because the updates are made only when the top-level child is changed which is not your case.
So in order to disable the parentViewController right button you should do:
self.parentViewController.navigationItem.rightBarButtonItem.enabled = NO
For more details regarding the nav bar button updates please check apple docs regarding the Updating Navigation Bar Items