avoid navigation transition error with view controller identifier - ios

I'm using Xcode 5 with storyboards and I should do something like this:
ViewController with a Start button that launches IntermediateViewController
IntermediateViewController that does an activity and then returns the value to the ViewController.
For the passage ViewController->IntermediateViewController I've set the start button to trigger a push segue. Actions are done and this part seems ok.
Now I have to go back to ViewController passing a string I got in IntermediateViewController methods.
If I use:
ViewController *viewController=[self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"viewController"];
viewController.passedString=_mystring;
[self.navigationController pushViewController:viewController animated:NO];
I get this error:
"Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted"
Is there a way to retrieve my viewController first instance through its identifier or any other solution that will lead the app back to viewController setting also its variable?
Thanks in advance

Even if it's not the exact answer to the question, I solved using this steps:
1) checked in storyboards that each element triggers only one action or segue, not both.
2) calling second view using:
[self.navigationController pushViewController:intermediateViewController animated:NO];
2) going back to previous view.
[self.navigationController popViewControllerAnimated:YES];
3) doing this before popping:
pass string between controllers

Related

Add UIViewController from another Storyboard

To get more structure in my project I started to use multiple storyboards.
Now I want to push a ViewController from another Storyboard. This works as aspected with no warnings. Unless I open the ViewController for a second time.
The push produces this error message: "nested push animation can result in corrupted navigation bar" and on pop it results in a crash with this message:
"Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted."
I push the ViewController with this code:
[self.navigationController pushViewController:controller animated:YES];
I assume there is something wrong with the NavigationController.
You should use this : https://github.com/rob-brown/RBStoryboardLink
It enables you to create storyboard links (segues) in your storyboards.
Using this you dont need to use pushViewControllers anymore (which cause your issues).
You will be able to use Segues and your life will be much more easier ;)
just in case method for segues :
[self performSegueWithIdentifer:#"MyStoryboard" sender:self];
Enjoy :)

iOS - How to change properties of root navigation controller from a pushed controller

I have a navigation controller with a root view controller that is WAViewController that it push WAInfoViewController passing to it some values. Now I use
[self.navigationController popViewControllerAnimated:YES];
to turn back and I want to restore the values changed in WAInfoController in WAViewController. How can I do it?
I guess if I create a reference to WAViewController like so I get wrong because it is already initialized
WAViewController *controller = [[WAViewController alloc]init];
controller.properties = VALUES;
UPDATE
Thanks for the answers guys. The problem is that in the topViewController I init an audio guide with play/pause buttons. When I go in info-page (the pushed view controller), I init the new synthesizer and the new utterance with the values of the topViewController so the audio guide will continue. Well, when I go back, the audio guide stops and it doesn't work no more
You can also do this via exit segues. You define an exit segue in WAViewController as
-(void)nameOfExitSegue:(UIStoryboardSegue*)segue {
WAInfoViewController* controller = segue.sourceViewController;
// Get changed values and do something with them.
}
In storyboard, you can hook up the action of the UI element you want to dismiss WAInfoVIewController to the exit segue icon. When you control-drag the line to the Exit Segue icon, you will see your exit segue methods pop up. Just select the exitSegue method you made.
You can do this a couple of ways. You could use delegation, which is probably the best way to do it -- you would create a delegate protocol in the WAInfoViewController, and the WAViewController would set itself as the delegate when it does the push. Before you do the pop back to WAViewController, you would call the delegate method to do what ever you need to do.
The other way, which is easier, would be to get a reference to the navigation controller's root view controller using its topViewController property.
WAViewController *controller = self.navigationController.topViewController;
controller.properties = VALUES;

Pushing and popping multiple view controllers causes random crash

I'm currently working on an app that builds a stack of controllers depending on the user.
Basically, I have a UIViewController that has a UIButton leading to another UIView Controller; that has a button leading to another view controller and so on. The view controllers are pushed so that when the user always press the button, I get a stack of multiple view controllers. The views are popped whenever the user wants to go back to the previous view controller.
Everything is working well (push and pop). However, at random instances, the app would crash. I noticed that it happens when there are already a large amount of views pushed, and I suspect that it can be a memory issue.
My question is, other than pushing the view controllers, is there an alternative so that I can avoid stacked views? Could it also be that the crash is not because of the stacked views but because I'm just missing something out? There is no error presented in the logs so I can't find out what's happening and I'm also new to iOS development.
Thank you very much!
Edit 1: There is no error in the logs but when the app crashes, there is this message:
Thread 1: EXC_BAD_ACCESS(code = 1, address = 0xd000000c)
Edit 2: This is how I am pushing the controller:
CustomController *custom = [self.storyboard instantiateViewControllerWithIdentifier:#"Custom"];
[self.navigationController pushViewController:custom animated:YES];
And this is how I popped it when the back button is pressed:
[self.navigationController popViewControllerAnimated:YES];
Edit 3: After enabling zombie objects in the scheme, I started to get this messages after multiple push and pop:
nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
Unbalanced calls to begin/end appearance transitions for
Do those messages say that the problem is actually on pushing the controller with animations? Thanks everyone!
Edit 4: I'll try to revise the question to make it more descriptive
This is my setup:
Controller A displays icons that corresponds to different places. You can click on the icon to push Controller B and display details for Location A.
Controller B displays information about Location A, with a button to show Controller A that now displays icons close to location of Location A. Now, you can again click an icon, say for Location B, and display details and so on.
When the user presses the back button, it should display the previous view controller. This is why I used push and pop. Is there a better way to handle this process. Thanks again!
My suggestion is: check if Zombie Objects is enabled and use the instrument "Allocations" to see if your application have, in fact, memory issues. With the informations provided by these tools, you can figure out what is happening with your application and work on it.
Tell me if you need help.
Good luck!
When push or pop, you should turn off animation. I think this causes crash when animation does not finish.
Push: self.navigationController pushViewController:custom animated:NO];
Pop: [self.navigationController popViewControllerAnimated:NO];
My guess is that you push multiple view controllers with animations - this may be a root cause of error. If you push more than one view controller you should animate only LAST push, say:
VC1 *vc1 = [self.storyboard instantiateViewControllerWithIdentifier:#"VC1"];
[self.navigationController pushViewController:vc1 animated:NO];
VC2 *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"VC2"];
[self.navigationController pushViewController:vc1 animated:NO];
VC3 *vc3 = [self.storyboard instantiateViewControllerWithIdentifier:#"VC3"];
[self.navigationController pushViewController:vc1 animated:YES];
However, i hardly imagine the situation where the multiple push would be necessary - i think it always leads to bad UX.

Redirect to a specific view controller

Just Have an issue and a "miss" in my programming "capacity".
I've got a tableview controller with some data parsed from a json.
When you choose a "news" you to to the detail view with all data in it.
Everything is ok, but I add a "check" If you are logged or not.
And if not you are "redirected" to login screen.
I try to do it with a segue (modal). It's working, but when I do it, my "navigation" is broken, like if he "lost" he's path.
I try to do it programatically like :
LoginViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self.navigationController pushViewController:controller animated:YES];
But when I'm doing it like that, nothing happen, my "detail view controller" load without redirecting
and got that log:
nested push animation can result in corrupted navigation bar Finishing
up a navigation transition in an unexpected state. Navigation Bar
subview tree might get corrupted.
Did someone have a hint for me ?
Thanks
you are doing it all wrong. you need to study the very basic of seque programming (storyboard).
follow this link
LoginViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self.navigationController pushViewController:controller animated:YES];
in storyboard you already have a push segue, & again you are pushing loginviewcontroller. thats why you are getting "nested push animation" warning.
This isn't the normal way to do it. You would normally present that login view controller modally.
If this is just the way you want it you could do it using the following steps:
1) Connect your DetailViewController to your TableViewController (not from cell itself, but from that yellow icon which represents your ViewController at the bottom black bar). Choose push if you like and add the identifier to that Segue (for example, "DetailSegue")
2) Connect your LoginViewController to your TableViewController just like you connected your DetailViewController and add the identifier to that segue (for example, "LoginSegue").
Now, when the user clicks on some cell, you wish to check if session is still active, if it is you will do [self performSegueWithIdentifier:#"DetailSegue" sender:self];, and if it is not, you will do [self performSegueWithIdentifier:#"LoginSegue" sender:self];
Hope this helps, cheers.
it's pretty tough to understand what you want to do, the question isn't too clear.
If you want to link to a scene in your storyboard though, create a segue to this by ctrl + click & drag from the initial scene, then give the segue an ID (do this by clicking on the segue and using inspector to set an ID)
then in your tableview controller, where ever you are picking up your tab (assuming this is in the tableview delegate method) you can call the segue programatically
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"YOURSEGUEID" sender:self];
}

How do I emulate 'Notes' from Apple and start the app with a navigation controller with a 'back' view?

I have an application that has a login page. It then moves to a navigation controller that has a collection view as its root view controller. When the app starts and there is only one item in the collection, I want to have the navigation controller automatically push to that item and allow the user to use 'back' to view the collection. This is the same behavior that is in 'Notes' from Apple.
The idea is to allow the user to immediately start to use the app and only 'discover' the need for the collection view after using the app for some time.
I am using IB, storyboards, and segues for my view transitions.
If I programmatically have the root view controller do a performSegue in its viewWillLoad: I get an error about causing a transition while a transition is still in process.
If I move the code calling performSegue into the didLoad, then the user sees a double transition.
A navigation controller usually manages the underlying stack itself. That is, you pass it an initial view controller, and then through segues or pushViewController:animated: the stack is altered. However, there is nothing stopping you from manually altering the stack. In prepareForSegue:sender:, you can check the number of items, and if it's 1, do something like this:
UIViewController *singleItemViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SingleItem"];
NSMutableArray *viewControllers = [sender.destinationViewController.viewControllers mutableCopy];
[viewControllers addObject:singleItemViewController];
sender.destinationViewController.viewControllers = viewControllers;
Now instead of starting at the first view controller of the stack, you start at the second one, with a back button to navigate back.
Actually, I found that the following worked the best for me.
if (/* reason to change back list*/) {
UIViewController * rootViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"backViewController"];
NSArray * viewControllers = #[rootViewController, self];
[self.navigationController setViewControllers:viewControllers animated:NO];
}
setViewControllers seems to be the best way to manipulate the stack.

Resources