I'm making an iOS app but I'm trying to send an object to another view controller but it throws me this error
Blockquote-[UINavigationController setUserObject:]: unrecognized selector sent to instance 0x156aa330
Here's my code:
loginViewController.m
this is user it's already allocated the object with the values of name, email, and lastname
#import "PerfilViewController.h"
#import "User.h"
#interface LogInViewController (){
User *user;
}
#end
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"loggedIn"]) {
user.name = self.nameText.text
user.lastname = self.lastNameText.text
PerfilViewController *pvc = [segue destinationViewController];
[pvc setUserObject: user];
}
}
In my destination controller I have this its as well allocated on viewDidLoad
#import "PerfilViewController.h"
#import "User.h"
#interface PerfilViewController (){
User *user;
}
#end
#implementation PerfilViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setViewValues];
[self.navigationItem setHidesBackButton:YES];
user = [[User alloc] init];
}
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
-(void)setUserObject:(User *)userToSet{
user = userToSet;
}
The problem is that the destinationViewController is a UINavigationViewController so PerfilViewController should be its rootViewController
if([[segue identifier] isEqualToString:#"loggedIn"]) {
UINavigationController *navigationController = [segue destinationViewController];
PerfilViewController *pvc = navigationController.rootViewController;
[pvc setUserObject: user];
}
My guess by looking at the code provided is that [segue destinationViewController] is not of the class PerfilViewController.
you could try checking to see if pvc has a method names setUserObject and then call that method if pvc responds to it. If not, then log out what class pvc actually is to help you debug. This should handle that:
if ([pvc respondsToSelector:#selector(setUserObject)]) {
[pvc setUserObject: user];
} else {
NSLog(#"pvc is of class \"%#\"", [s class]);
}
Related
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I am trying to pass data from one ViewController to another ViewController.
Firstviewcontroller.m
-(void)NavigateToAnotherScreen:(NSMutableDictionary*)dict{
[self performSegueWithIdentifier:#"NavDashBoardToInfo" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NavDashBoardToInfo"])
{
InfoViewController *vc = [segue destinationViewController];
[vc setAppointmentDictionary:dict];
}
}
Secondviewcontroller.h
#property (strong, nonatomic) NSMutableDictionary *AppointmentDictionary;
Secondviewcontroller.m
#synthesize AppointmentDictionary;
- (void)viewWillAppear:(BOOL)animated{
NSLog(#"dict===>%#",AppointmentDictionary); // This gives me null
}
Please help me. What i am doing wrong.
I am getting AppointmentDictionary = (null) in viewwillappear.
Though I am doing proper copy of this.
try this
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setAppointmentDictionary:)]) {
[segue.destinationViewController performSelector:#selector(setAppointmentDictionary:)
withObject:dict];
}
}
Try this one:
-(void)NavigateToAnotherScreen:(NSMutableDictionary*)dict
{
[self performSegueWithIdentifier:#"NavDashBoardToInfo" sender:dict];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
InfoViewController *info = segue.destinationViewController;
info.AppointmentDictionary = sender;
}
If you are using performsegue for navigation then you can use below method for transferring data between ViewControllers
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NavDashBoardToInfo"])
{
InfoViewController *info = [segue destinationViewController];
info.AppointmentDictionary = "Value you want to pass";
}
}
You are creating InfoViewController instance and not pushing that view controller. You doing a "performSegueWithIdentifier" here new instance will create, so you first instance "info" is not passing here. You can do in other way.
InfoViewController *info = [[InfoViewController alloc] init];
info.AppointmentDictionary = [dict mutableCopy];
[self.navigationController pushViewController: info animated:true];
Option 2:
-(void)NavigateToAnotherScreen:(NSMutableDictionary*)dict{
[self performSegueWithIdentifier:#"NavDashBoardToInfo" sender: [dict mutableCopy]];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"NavDashBoardToInfo"]) {
InfoViewController *viewController = (InfoViewController *)segue.destinationViewController;
viewController.AppointmentDictionary = (NSMutableDictionary *)sender;
}
}
In the prepareforsegue method you have to pass the value like mentioned above.
Note: make sure your destination view controller is InfoViewController
If you are using performSegueWithIdentifier then provide the body in function . Don't create any new instance using code and provide segue in storyboard -
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"YourController_Segue"]) {
YourController *viewController = (YourController *)segue.destinationViewController;
viewController.AppointmentDictionary = (NSMutableDictionary *)sender;
}
}
I have this code below that send the row to my another class:
[self performSegueWithIdentifier:#"MeInfos" sender:[NSString stringWithFormat:#"%d",(int)indexPath.row]];
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
MeInfosViewController *viewController = [[MeInfosViewController alloc] init];
viewController.paramethersToLoad = (NSString*)sender;
NSLog(#"Will receive -> %#",sender);
}
In my another class (MeInfoViewController) I have:
.h
#property (nonatomic, retain) NSString *paramethersToLoad;
.m
#synthesize paramethersToLoad;
-(void)viewDidAppear:(BOOL)animated{
NSLog(#"What comes? -> %#",paramethersToLoad);
}
This code has a little problem, in console I receive the following messages:
Will receive -> 4
What comes? -> (null)
Why this is happening and what the best way to solve it?
The view controller you're creating in prepareForSegue: isn't the instance that the segue will actually load. The view controller that actually gets displayed is created by the iOS runtime, and is passed to you as a property in the segue.
What you want is:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
MeInfosViewController *viewController = (MeInfosViewController *)segue.destinationViewController;
viewController.paramethersToLoad = (NSString *)sender;
}
Your prepareForSegue should look like this :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"MeInfos"]) {
// Get reference to the destination view controller
MeInfosViewController *viewController = [segue destinationViewController];
viewController.paramethersToLoad = (NSString*)sender;
}
}
What is wrong with below code. It is crashing with SIGABRT (unrecognized selector sent to instance)
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"%#",valueName);
if([segue.identifier isEqualToString:#"pushView"])
{
secondViewController *svc = (secondViewController *)[segue destinationViewController];
svc.passedName = valueName;
}
}
The valueName iVar is an NSString which i want to pass.
1) Don't forget to embed you FirstViewController with NavigationController
2) Don't forget to set your segue identifier.
3) Use the same code you have:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//for example if you value is "123"
NSString *valueName = #"123";
NSLog(#"%#",valueName);
if([segue.identifier isEqualToString:#"pushView"])
{
secondViewController *svc = (secondViewController *)[segue destinationViewController];
svc.passedName = valueName;
}
}
4) Now, in your secondViewController, log you value in ViewDidLoadto see if it is passed...
- (void)viewDidLoad
{
NSLog(#"value: %#", self.passedName);
}
5) The result you should get:
I created a subclass of UIStoryboardSegue in order to achieve a modal segue with optional animation.
(subclass of UIStoryboardSegue):
.h
#import <UIKit/UIKit.h>
#interface ModalSegue_OptionalAnimation : UIStoryboardSegue
#property (readwrite) BOOL withAnimation;
#end
.m
#import "ModalSegue_OptionalAnimation.h"
#implementation ModalSegue_OptionalAnimation
-(void) perform{
BOOL _withAnimation_Va = self.withAnimation;
[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:_withAnimation_Va];
}
#end
But I am unsure now how to call this property from the outside.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"segue_qVC_to_cVC_checkAnswer"]) {
CheckAnswerViewController *cVC = [segue destinationViewController];
if(segue_QVC_ISEXAM) {
//Something like this:
//segue.withAnimation = NO;
//Settings the property to NO is like 'I dont animation when performing the segue'
}
....
In my storyboard I already set the segue to custom with the just created class.
Try something like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"segue_qVC_to_cVC_checkAnswer"]) {
CheckAnswerViewController *cVC = [segue destinationViewController];
if(segue_QVC_ISEXAM) {
ModalSegue_OptionalAnimation *customSegue = (ModalSegue_OptionalAnimation *)segue;
customSegue.withAnimation = NO;
//Something like this:
//segue.withAnimation = NO;
//Settings the property to NO is like 'I dont animation when performing the segue'
}
....
I wanna to pass data between controller, but I am getting this error, and I am blocked here :s
Error :
[UITabBarController setUID:]: unrecognized selector sent to instance
Code :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString *test = (NSString *)sender;
if ([segue.identifier isEqualToString:#"segueno"]) {
FirstViewController *VC = (FirstViewController *)[segue destinationViewController];
VC.uID = test;
NSLog(#"%#",VC.uID);
}}
Here is storyboaard
Check what is actual type of VC during runtime. Looks like you cast to wrong type.
To check real type during runtime set breakpoint on line VC.uID = test;. In debug window you should have something like:
VC = (RealClass *) 0x312321312
Real class is not what you expected.
The most possible reason, that VC is UITabBarController. So you have to replace
FirstViewController *VC = (FirstViewController *)[segue destinationViewController];
with
UITabBarController *tabBarController = (UITabBarController *)[segue destinationViewController];
// replace 1 with real index of your FirstVC
FirstViewController *VC = [[tabBarController viewControllers] objectAtIndex:1];
segue destination is UITabBarController. so you need to check viewcontrollers list. then based on that u can look for uID.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString *test = (NSString *)sender;
if ([segue.identifier isEqualToString:#"segueno"]) {
FirstViewController *firstVC ;
UITabBarController *destinat = [segue destinationViewController];
if ([destinat isKindOfClass:[UITabBarController class]]) {
for (id listOfViewControllers in [destinat viewControllers]) {
if ([listOfViewControllers isKindOfClass:[FirstViewController class]]) {
firstVC = listOfViewControllers;
break;
}
}
}
firstVC.uID = test;
NSLog(#"%#",firstVC.uID);
}}
Here is how I pass managedObjectContext between segues
In your class where you will pass the data use prepareForSegue call. (The assumption is this class has a variable called _managedObjectContext which can be passed along to the segue class)
Class to Segue From:
.h file:
#property (weak, nonatomic) NSManagedObjectContext *managedObjectContext;
.m file:
#synthesize managedObjectContext
The call to #synthesize will make the following:
a local variable called _managedObjectContext
a method to getManagedObjectContext
a method to setManagedObjectContext
Additionally add the following method to your class
// Pass on managedObjectContext
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// If the destination VC is able to take the setManagedObjectContext method the current objectContext will be passed along.
if ([segue.destinationViewController respondsToSelector:#selector(setManagedObjectContext:)]) {
[segue.destinationViewController performSelector:#selector(setManagedObjectContext:)
withObject:_managedObjectContext];
} else {
NSLog(#"Segue to controller [%#] that does not support passing managedObjectContext", [segue destinationViewController]);
}
}
Then in my "class" to receive the data I do:
in the .h file i have
#property (weak, nonatomic) NSManagedObjectContext *managedObjectContext;
and in the .m file i have:
#synthesize managedObjectContext;
What this does (with syntehsiation) is make a setManagedObjectContext and getManagedObjectContext call. Upon being about to segue I check to make sure the destinationController will "respond to" this method, if so the data gets set.
clear?