I have returned to a project to make some minor changes and find that I'm getting a NSInvalidArgumentException presenting a popover. I'm almost certain that this worked previously. I'm using Xcode 6.3.1 and iOS 8.3 SDK.
I believe the issue is to do with the segue object being sent to prepareForSegue which is a UIStoryboardPushSegue - should it not be a UIStoryboardPopoverSegue if that is what is defined in the storyboard segue?
The error I'm receiving is -[UIStoryboardPushSegue popoverController]: unrecognized selector sent to instance
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DatePickerViewController *vc = (DatePickerViewController*)segue.destinationViewController;
[vc setQuestion:self.question];
[vc setDismissPopoverDelegate:self];
if([segue.identifier isEqualToString:#"CompletionDateSegue"])
{
[vc.datePicker setDate:self.question.completionDate animated:YES];
[vc setPropertyName:#"completionDate"];
}
else if ([segue.identifier isEqualToString:#"TargetCompletionDateSegue"])
{
[vc.datePicker setDate:self.question.targetCompletionDate animated:YES];
[vc setPropertyName:#"targetCompletionDate"];
}
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
[popoverSegue.popoverController setPopoverContentSize:CGSizeMake(320, 256) animated:YES];
}
Related
I have project where I'm using UINavegationController between to views:
I'm using the navigation controller because I'm using modal presentation (Flip)
But my problem is I'm trying to pass NSString Object to ViewControllerB:
Code:
- (IBAction)goToB:(id)sender {
[self performSegueWithIdentifier:#"goToB" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"goToB"]) {
BViewController *vc = (BViewController*)[segue destinationViewController];
vc.commigFromA = #"I'm going to B!";
}
}
But I'm getting this error:
-[UINavigationController setCommigFromA:]: unrecognized selector sent to instance 0x7ff1c4830c00
Any of you knows why or a way around this error?
I'll really appreciate your help
It's crashing because the destinationViewController on the segue is actually a UINavigationController, not a BViewController, and UINavigationControllers don't know about a property comingFromA. You can test this theory by replacing prepareWithSegue like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"goToB"]) {
UINavigationController *nvc = (UINavigationController*)[segue destinationViewController];
BViewController *vc = (BViewController*)nvc.viewControllers[0];
vc.commigFromA = #"I'm going to B!";
}
}
I declared a GamePicerViewController (subclass of UITableViewController) .But I got a bug in the prepareForSegue:sender: method . The console says that gamePickerViewController is a UINavigationController. Have any ideas?
I post the GamePickerViewController.h PlayerDetailsViewController.m and the console in the pic abve.
problem solved.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"PickGame"]) {
UINavigationController *controller = segue.destinationViewController;
GamePickerViewController *gamePickerViewController = [controller viewControllers][0];
gamePickerViewController.delegate = self;
gamePickerViewController.game = _game;
}
}
I forgot the line:
UINavigationController *controller = segue.destinationViewController;
I have a SplitViewController App with 2 initial controllers:
leftViewController (master)
rightViewController (detail)
my rightViewController (detail) has the delegate of the splitViewController for presenting a button which shows/hides my menu (master)
my leftViewController (master) is a menu application, when I select any element of the menĂº I trigger a segue connected to my master and it replaces my detailViewController for the selected element of menu
when I do that and if I try to rotate my iPhone for hide menu my app crashes and says:
*** -[rightViewController respondsToSelector:]: message sent to deallocated instance
I guess it is because my splitViewController wants to communicate with its delegate, its old rightViewController, but it is gone, it has been replaced on my view,
maybe I need whether:
reasign my delegate to my new viewController (detail)
or
remove delegate of my rightViewController and assign it then to my newViewController
also tried this in my new viewController:
#interface newViewController ()<UISplitViewControllerDelegate>
#end
#implementation newViewController
- (void)viewDidLoad
{
UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
...
#end
but still not working... I get the same message
how do I fix this???
thanks in advance
EDIT: add my segue code for helping to answer my question
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"viewSceneAgenda"]) {
[segue.destinationViewController setTitle:#"Citas"];
[segue.destinationViewController setUserIDElement:UID_CUS];
[segue.destinationViewController setOverallAppointments:overallDates];
}
}
Maybe you have to pass your delegate as you said to your newViewController... why don't you add this in your leftViewController (master)...
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showNewViewControllerScene"]) {
UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController;
splitViewController.delegate = segue.destinationViewController;
}
}
just replace the segue identifier (showNewViewControllerScene) to match with yours on your storyboard
Gonna complement Jesus Answer
Since I'm working with several segues, all of them must have the delegate of my UISplitView, also since iPhone doesn't support splitviews, I added a condition for assigning the delegate just if the user is running this app on any iPad
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[UIDevice currentDevice].model hasPrefix:#"iPad"]) {
UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController;
splitViewController.delegate = segue.destinationViewController;
}
if ([segue.identifier isEqualToString:#"viewSceneAgenda"]) {
[segue.destinationViewController setTitle:#"Citas"];
[segue.destinationViewController setUserIDElement:UID_CUS];
[segue.destinationViewController setOverallAppointments:overallDates];
}
}
I am having trouble with a Navigation Controller in my iOS project which uses Storyboards.
The main part of the project is a UITabBar. When the app loads for the very first time the screen RegisterViewController is presented:
When the user taps on the "Register" button a HTTP POST request is made, then upon receiving the response (JSON object) the screen QuestionnaireViewController is presented using:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
QuestionnaireViewController *questionnaireViewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"QuestionnaireView"];
[questionnaireViewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[questionnaireViewController setQuestionsAndAnswers:_questionsAndAnswers];
[self presentViewController:questionnaireViewController animated:NO completion:nil];
When the user taps on a cell in QuestionnaireViewController a message is sent to prepareForSegue:sender:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navigationController = segue.destinationViewController;
AnswersViewController *answersViewController = [[navigationController viewControllers] objectAtIndex:0];
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSArray *answers = [[_questionsAndAnswers objectAtIndex:indexPath.row] objectForKey:#"answers"];
[answersViewController setAnswers:answers];
}
At this point the app crashes with an error of:
-[AnswersViewController viewControllers]: unrecognized selector sent to instance.
Below is a more comprehensive overview of my storyboard, which may help in understanding where I have gone wrong:
I am stumped as to how to fix this, and am hoping that someone out there is able to help.
Thanks,
Nick
First, you should present the navigation controller, not its root view controller. Then when you want to populate the root view controller with some data, you need to reference it as the navigation controller's root view controller:
UINavigationcontroller *questionnaireNavController = [self.storyboard instantiateViewControllerWithIdentifier:#"QuestionnaireNavigationController"];
[questionnaireNavController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
QuestionnaireViewController *qvc = (QuestionnaireViewController *)[questionnaireNavController topViewController];
[qvc setQuestionsAndAnswers:_questionsAndAnswers];
[self presentViewController:questionnaireNavController animated:NO completion:nil];
Second, in prepareForSegue:sender: you don't need to reference a navigation controller at all:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
AnswersViewController *answersVC = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSArray *answers = [[_questionsAndAnswers objectAtIndex:indexPath.row] objectForKey:#"answers"];
[answersVC setAnswers:answers];
}
You are not getting the navigationController properly. Instead of segue.destinationViewController, use self.navigationController
By calling segue.destinationViewController, you are getting a pointer to the VC you are segueing to (AnswersViewController) which doesn't understand the message viewControllers because it is not a UINavigationController.
Also the AnswersViewController is objectAtIndex:1 I believe, check this though.
I have a ViewController that has a couple of buttons on it created in Interface Builder. The first button will display a popover linked up in IB, it is linked to a UINavigationController and has a TableView under it with a class of PopupViewController.
The second button, I have an action setup for goToCategory and when clicking on that, I want to set a property on the PopupViewController
ViewController.m
//go to category
-(IBAction)goToCategory:(id)sender{
NSLog(#"GO TO CAT");
//PopupViewController *popupVC = [self.storyboard instantiateViewControllerWithIdentifier:#"popoverVC"];
//popupVC.currentLevel = 1;
[self performSegueWithIdentifier:#"popoverSegue" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSLog(#"seg1");
if ([[segue identifier] isEqualToString:#"popoverSegue"]){
//PopupViewController *popupVC = (PopupViewController *)[[segue destinationViewController] visibleViewController];
//PopupViewController *popupVC = [segue destinationViewController];
PopupViewController *popupVC=[[[segue destinationViewController]viewControllers]objectAtIndex:0];
popupVC.test = #"just a test";
NSLog(#"seg2");
}
}
PopupViewController.h
#property (nonatomic, strong) NSString *test;
PopupViewController.m
#synthesize test;
-(void)viewDidLoad{
NSLog(#"test: %#", test); //returns test: (null)
}
I've found a lot of answers on SO, hence some of the commented out lines in my prepareForSegue. But none of these set the value of test. PopupViewController *popupVC = [segue destinationViewController]; throws an error due to it referring to the UINavigationController so I can't use that as it is, even though that seems to be the way to do it in a lot of answers I've seen. But no matter which way I try doing it, the output is always null?
UPDATE:
PopupViewController *popupVC = (PopupViewController *)[[segue destinationViewController] visibleViewController]; and PopupViewController *popupVC=[[[segue destinationViewController]viewControllers]objectAtIndex:0]; from my prepareForSegue above both work on the 6.1 simulator. My iPad's iOS is 5.1.1 which it isn't working on. Is there something different I need to do for iOS 5?
Try this
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"seg1");
if ([[segue identifier] isEqualToString:#"popoverSegue"])
{
UINavigationController *navController = (UINavigationController*)[segue destinationViewController];
PopupViewController *popupVC = [navController topViewController];
popupVC.test = #"just a test";
NSLog(#"seg2");
}
}