RearViewController.m
-(IBAction)unwindFromViewController:(UIStoryboardSegue *)segue
{
if ([segue.identifier isEqualToString:#"unwindToViewController"]) {
ViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[self presentViewController:detail animated:YES completion:nil];
}
}
If I click back from my RearViewController the ViewController is not presented instead it just peeps and goes off(again shows RearViewcontroller).
Image2
I give you a solution for your question.
1.First remove triggered segue connection.
2.After that give push segue connection to Back to your required view controller.
3.Click Back Button Segue and give Identifier name as "goToMainViewController" or whatever you want just give there.Also segue should be "push".
Thank You
Related
I am new in iOS world.I am creating one tab-bar sample app.
There is one button in first view-controller when i click this button it goes to to second view-controller.In second view-controller i use one gridview and i left 100 space at bottom.
now in second view-controller i have to add one tab bar so i go to Editor->Embedin->Tabbar controller and run application but i do not see tab bar here.I also try to use tab bar controller on object library but same issue i found.
Why tab bar is not displaying in second view-controller.Any suggestion ?
button click event :-
SecondVC *vc=[self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
[self.navigationController pushViewController:vc animated:YES];
Thanks .
If you have the SecondVC embedded in a TabBarVC you need to present the TBVC instead of the SecondVC in order for the Tab Bar to actually appear.
So instead of doing:
SecondVC *vc=[self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
[self.navigationController pushViewController:vc animated:YES];
you need to do:
TabBarVC *vc=[self.storyboard instantiateViewControllerWithIdentifier:#"TabBarVC"];
[self.navigationController pushViewController:vc animated:YES];
This will add to the navigation stack the Tab Bar View Controller.
This might be the implementation you are looking for
Button to viewcontroller SecondVC set segue identifer name as Pass
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{if ([[segue identifier] isEqualToString:#"Pass"])
{
SecondVC* vc = [[SecondVC alloc] init];
vc = (SecondVC ) [[(UINavigationController)[[self.tabBarController viewControllers] objectAtIndex:0] viewControllers] objectAtIndex:0];
}
}
I am trying to navigate to "Home" view controller and for this I have written the following code in the ContainerViewController. But once the code executes, the application hangs and it show 100% CPU usage. Please help.
- (IBAction) home:(UIButton *)sender
{
HomeViewController *homeViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
[self.navigationController pushViewController:homeViewController animated:YES];
//[self presentViewController:homeViewController animated:YES completion:nil];
}
I have a question for you
1-If You want to push SecondViewController on to FirstViewController then your code is good enough
2-If you have a containerview in firstViewController and you want to add SecondViewcontroller's view to firstViewController
then use this code
UIViewController*vc1 = [[test1 alloc]initWithNibName:#"SecondViewController" bundle:nil];
//add to the container vc which is self
[self addChildViewController:vc1];
//the entry view (will be removed from it superview later by the api)
[self.view addSubview:vc1.view];
I think you want an unwind segue here. In your first view controller add :
- (IBAction)unwindToFirstViewController:(UIStoryboardSegue*)sender
{
}
You then need to hook up each of your view controllers home button to the green Exit button at the bottom of the view controller, choosing the unwindToMainMenu option. This will then take you back to the first view controller when pressed.
Have you tried popping the current view?
navigationController?.popViewControllerAnimated(true)
or just popping to root?
navigationController?.popToRootViewControllerAnimated(true)
or setting a new stack?
navigationController?.setViewControllers(homeViewController, animated: true)
The code is in Swift but it would work the same in ObjectiveC
I have an UITabBarController that has 3 buttons. The second button points to ViewController1 which is connected to another view called ViewController2. After I tap a button in ViewController2 I programmatically present ViewController1 again, that works perfect except one thing. After I "arrived" to ViewController1 the tab bar disappears.
I'm using this method to navigate back to ViewController1. (exactly I navigate to its navigation controller, but already tried with the view)
- (void)presentViewControllerAnimated:(BOOL)animated {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboard" bundle:nil];
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
}
I call here the first method
- (void)didTapButton:(id)sender {
UIButton *button = (UIButton *)sender;
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
[self presentViewControllerAnimated:YES];
}
This method hides the tab bar in the ViewController2, I already tried without it, therefore there is no problem with it.
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
I can't figure out why this thing happens, I think it's a fair solution, that worked well for a several times when I needed to present views. I've read it can happen with segues, but I'm doing it with code without segues.
Actually your code works right. There should not be tab bar when you present FirstViewController from SecondViewController. Because when you call instantiateViewControllerWithIdentifier its basically creates a new instance of that view controller, and of course, there is no tab bar.
The right way to go back to your first view controller is to pop SecondViewController (or dismiss it, if it presented modally). So your final code should be like this
- (void)didTapButton:(id)sender {
// If this view controller (i.e. SecondViewController) was pushed, like in your case, then
[self.navigationController popViewControllerAnimated:YES];
// If this view controller was presented modally, then
// [self dismissViewControllerAnimated:YES completion:nil];
}
And of course, your view controller hierarchy in storyboard must be like this:
-- UINavigationController -> FirstViewController -> SecondViewController
|
->UITabBarController____|
-...
-...
I've tried the same and got the same result.
My solution was simple, on the push do this :
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
firstViewNavigationController.hidesBottomBarWhenPushed = true; // Insert this and set it to what you want to do
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
and then remove your
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
I have a simple app with 2 screens.
When I press a button to go from the first to the second, everything is performed successfully (including animation). However, when I click the back button on the second screen, I get the following warning:
Warning: Attempt to present <getTextViewController: 0x8f6aa30> on <SecondViewController: 0x946cc80> whose view is not in the window hierarchy!
EDIT: Please don't refer me to other questions regarding above warning - I already saw those, and they refer to other issues.
However, it still switches back to the first screen. Yet, the animation of the segue does not perform.
Also: Information (such as inputted text) in the first screen remains when I return to the first screen, while information in the second screen resets every time the screen comes up.
Here is how I call both operations:
Segue from View 1 to View 2:
Name: F21, Style: Modal, Transition: Cross Dissolve, Animation: True.
Segue from View 2 to View 1:
Name: F12, Style: Modal, Transition: Cross Dissolve, Animation: True.
Code in getTextViewController.m (View 1):
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"F21"]){
UIViewController *v = [segue destinationViewController];
[self dismissViewControllerAnimated:NO completion:nil];
v = self;
}
}
-(void)performSegue:(NSString*)str{
[self performSegueWithIdentifier:str sender:self];
}
//In some other method:
[self performSegue:#"F21"];
Code in SecondViewController.m (View 2):
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"F12"]){
UIViewController *v = [segue destinationViewController];
[self dismissViewControllerAnimated:NO completion:nil];
v = self;
}
}
-(void)performSegue:(NSString*)str{
[self performSegueWithIdentifier:str sender:self];
}
- (IBAction)goBack:(id)sender {
[self performSegue:#"F12"];
}
I would very much appreciate any help to understand why the first segue works while the second doesn't.
Thank you,
Dean
NOTE: Here is the full project - https://github.com/dean13-meet/firstIOSApp
EDIT: Updated git.
Im not exactly sure what you're trying to do in your prepareForSegue, their is no need to be dismissing VC's there. If you want to have a simple app where you go from VC1 to VC2 and then back again, your best bet is to use a segue and an unwindSegue.
So in your storyboard control drag from a button on VC1 to VC2 and select your segue type. Then in VC1.m setup the unwind segue such as:
- (IBAction)unwindFromViewController:(UIStoryboardSegue *)segue
{
//empty implementation
}
Finally, in your VC2 control drag from the back button to the green exit icon on VC2 and select your unwindFromViewController method.
That should do what you're looking for.
For the sake of simplicity, I would suggest using a push segue opposed to modal because it takes care of all the back buttons for you. If you don't like the idea of a navigation controller however, try dismissing the view with the following: Moving back from a Controller to a previous one
I have a tab bar controller with a navigation controller per tab. The nav controllers have view controllers. I then have a Login View Controller not connected to the tab bar controller that I call with the code below if a user needs to login or logs out.
I am seeing some strange behavior when I try to conditionally push a view controller based on if a user is logged in or not.
My logic looks like this:
if(currentUser){
}else{
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
When the view is pushed it look as if the the Login View is pushed and another Login View is pushed on top of it.
For logout I have the same code in a segue:
if ([segue.identifier isEqualToString:#"LogoutView"]) {
[self logOut];
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
In this instance I see the same double push and each time I click my login button it pushes another Login View. This happens infinitely. I then get the warning:
Finishing up a navigation transition in an unexpected state.
Navigation Bar subview tree might get corrupted.
When I press back in the navigation, the app crashes with the error:
NSInvalidArgumentException', reason: 'Can't add self as subview'
Am I not correctly pushing the login view controller?
Segues instantiate new controllers, and perform the transition form the source controller to the destination controller. Therefore, you should neither be instantiating the controller in code, nor pushing it with pushViewController:animated:. If the buttons (rather than the controller) are triggering the segues, then you only need to get a reference to the destination controller (segue.destinationViewController), and use that to hide the bottom bar,
-(void)prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender {
if ([segue.identifier isEqualToString:#"LogoutView"]) {
[self logOut];
LoginViewController *svc = segue.destinationViewController;
svc.hidesBottomBarWhenPushed = YES;
}
}
If you need to do this conditionally, then the segue should be connected directly from the controller, not a button. Then you need to call performSegueWithIdentifier: in some method where you have the logic to determine which (or whether a) segue should be performed.