Push segues can only be used by UINavigationController Error - ios

Getting a weird error when attempting to do a "push" sequence on a UIViewController.
I have embeded two UINavigationControllers into a root UIViewController.
I am basically attempting to make it so when the > button is pressed it pushes to the "View Controller."
Any ideas why I am getting the following error?:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
This is my storyboard:
http://cl.ly/image/3K0s3J1U1A3W
I am getting to the RecordViewController like so:
RecordViewController *record = [self.storyboard instantiateViewControllerWithIdentifier:#"RecordView"];
[self presentViewController:record animated:YES completion:nil];

If you want to push view controllers to a presented view controller, then your presented view controller must be a UINavigationController. In your case, give the leftmost navigation controller an identifier (i.e RecordNavigationController) and convert your code to:
UINavigationController *recordNavigationController = (UINavigationController*)[self.storyboard instantiateViewControllerWithIdentifier:#"RecordNavigationController"];
[self presentViewController:recordNavigationController animated:YES completion:nil];

Related

How to navigate to a View Controller embedded in tab bar controller

I have a viewControllerA embedded in a navigationController.From this viewControllerA I want to navigate to another viewControllerB which is embedded in a tabBarController.
So I have a setup like -
viewControllerB is embedded in a navigationController and then this is embedded in tabBarController.
In viewControllerA I have a button from where I want to push to viewControllerB.
This is what I am trying to do -
-(void)areaBtnClicked:(id)sender{
NSLog(#"btn clicked");
UITabBarController *tbc = [self.storyboard instantiateViewControllerWithIdentifier:#"tabController"];
[self.navigationController pushViewController:tbc animated:YES];
}
However the app is crashing with a error message as -
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Are you sured, that your controller has that identifier "tabController" ?
Check your storyboard.
Well apparently deleting the app from simulator solved the problem.

how to have a UIViewCojntroller that is instantiated out of a Storyboard be embedded within a UINavigationController

I have a UIViewController called "Yellow" in my storyboard that I'm adding like this:
_detailVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Yellow"];
_detailVC.location=cell.location;
self.incomingView = _detailVC.view;
[self addChildViewController:_detailVC];
[self.view addSubview:self.incomingView];
self.incomingView.alpha = 0;
[_detailVC didMoveToParentViewController:self];
I need this UIViewController to exist within a UINavigationController as I'm using a push segue and it is giving
me the following error:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'pushDetailVC'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
If I go to the view for the "Yellow" view controller, and "embed in Navigation Controller", I still
get the same problem.
How would I embed this UIViewController in a UINavigationController so that the push segue works
correctly?
When you instantiate a view controller from the storyboard, you don't automatically get any controller that it might be embedded in. You're telling the system to give you a DetailVC, and that's what it gives you. If you want the navigation controller, then you need to instantiate it, and it will automatically instantiate its rootViewController (which is Yellow) because its hooked up with a relationship segue.
UINavigationController *nav = [self.storyboard instantiateViewControllerWithIdentifier:#"Nav"];
_detailVC = (DetailVC *)nav.topViewController; // replace DetailVC with whatever your class name is
_detailVC.location=cell.location;
To use a push segue, the UIViewController you are pushing from must be within the same UINavigationController as the one you are pushing to. If you don't want that top bar to be displayed on the view you are pushing from, then you should consider a different type of segue to make the Yellow view appear (though the yellow may still be within a Navigation Controller if it has its own hierarchy to take care of).

iOS: Presenting a UIViewController modally (form sheet/page sheet) over splitViewController

I have a UISplitViewController (is the rootViewController)
and a UIViewController, vc1.
I'm trying to present vc1 over my split view controller from the MasterViewController part:
vc1.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentViewController:vc1 animated:YES completion:nil];
this raises an exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'Application tried to present modally an active
controller <MasterViewController: 0x8c5dd30>.'
...and crashes.
Tried this:
[self.splitViewController presentViewController:vc1 animated:YES completion:nil];
This raises an exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason:'Application tried to present modally an active
controller <UISplitViewController:0x8c7e3a0>.'
However, if i try it with the interface builder (segues), it works.
How do i present a view controller, modally (as pages sheet or form sheet), over a split view controller, programmatically?
You can tell the DetailView controller to show it. Something like this I suppose.
DetailVC *detailVC = [self.splitViewController.viewControllers objectAtIndex:1];
[detailVC presentViewController:vc1 animated:YES completion:nil];
I suppose the issue is that your master is presenting a detail view and that's why it can't present anything else, so you ask the detail view to do it for you.

crash passing parameter from one viewcontroller to another

I'm trying to pass parameter from one view controller to another, but application crashes with exception.
My code is this:
SelectedItemViewController *nextView = [storyboard instantiateViewControllerWithIdentifier:#"SelectedItemViewID"];
nextView.m_selectedItemId = [NSNumber numberWithInt:777];
[self presentViewController:nextView animated:YES completion:NULL];
And I have the following in my stack:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController setM_selectedItemId:]: unrecognized selector sent to instance 0x9c765d0'
In your storyboard, the view controller with identifier SelectedItemViewID is a navigation controller, not a SelectedItemViewController. So, before you set m_selectedItemId you should access the navigation controllers root view controller (which should be your SelectedItemViewController).
I found solution here: instantiateViewControllerWithIdentifier and pass data
What should be done in case if you want to pass parameter to view controller via navigation controller:
UINavigationController *navigationController = [storyboard instantiateViewControllerWithIdentifier:#"SelectedItemViewID"];
SelectedItemViewController *nextView = navigationController.viewControllers[0];
nextView.m_selectedItemId = [NSNumber numberWithInt:777];
[self presentViewController:navigationController animated:YES completion:NULL];
When you select the view controller in your storyboard, is the class set to SelectedItemViewController?
Obviously you seem to have a #property ... m_selectedItemId (or at least setter method setM_selectedItemId) on SelectedItemViewController, otherwise your code wouldn't even compile. But it seems that [storyboard instantiateViewControllerWithIdentifier:#"SelectedItemViewID"] doesn't really return the expected SelectedItemViewController. Hence I have the feeling that you forgot to set the correct class name to SelectedItemViewController in your storyboard.

IOS opening other view controller on buttonclick not working with storyboards

I am having a silly problem with opening another viewcontroller on a buttonclick.
On my viewcontroller on my storyboard, I have a button. When a users clicks on this button, a new viewcontroller should be opened. As far as I know, there are 2 ways to do this.
in code
on the storyboard itself
Both methods are not working for me.
First the problem with storyboards:
(source: livefilestore.com)
I have connected my mainViewController with a navigationController, and I have connected my button with my next view (for adding an item). However, when I run the program, I get the following error:
'NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
I really don't understand this error, because the mainviewcontroller IS managed by a UINavigationController.
So, as this didn't work, I tried to handle it in code. I connected the buttonclick action to the mainViewController.h file and implemented it in the .m file.
This is the action method when a user clicks on the button:
- (IBAction)actionBtnAdd:(id)sender {
AddInventoryViewController *addinvController = [self.storyboard instantiateViewControllerWithIdentifier:#"AddInventoryViewController"];
[self presentViewController:addinvController animated:NO completion:nil];
}
The other viewcontroller is in the same storyboard, and the ID of the other viewcontroller is "AddInventoryViewController". This gives me the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Anybody who know the problem? What would be the best approach to solve this?
Your navigation controller is not the initial view controller. Select your nav controller on storyboard, go into Attributes Inspector and select "Is Initial View Controller".
Make your navigation controller Initial View Controller.
Then create a push-segue from button to target controller.
Then you can use following method to make some adjustments before pushing:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"TargetSegue"]) {
TargetViewController *vc = segue.destinationViewController;
//vc.items = nil;
}
}
Update:
There are more options:
If your initial view controller is tabbar: Add segue from one of the tabs to navigation controller which contains your view controller.
If your initial view controller is another navigation controller:
Remove navigation controller which contains your view controller. Then add the segue between the thirdViewController and the source from which it is presented. The you can use push segue between the button and the target view controller.
If you want to do it programmatically:
Remove navigation controller which contains your view controller. Push the thirdViewController from your currently presented navigation controller. Push the targetViewController from buttonAction.
Hope it will help :)
In your Xcode .Click the storyboard on the left side and on top select Editor->EmbedIn->Navigation controller .It will automatically add your navigation controller to the first view controller .Then it would work
You have to set the Navigation controller as the first controller
See before the Navigation controller there is the storyboard starting arrow
Under your IBAction method instead of using
[self presentViewController:addinvController animated:NO completion:nil];
use this code and check
[self.navigationController pushViewController:addinvController animated:YES];

Resources