MainViewController pushViewController:animated:]: unrecognized selector sent to instance 0x1459e980 - ios

I'm trying to add a functionality to open a specific view controller on opening the notification on my iOS app. As I am new to iOS, I have a few doubts.
I have written the backend, which sends the promo id as a custom parameter. I am able receive the JSON object on XCode, read the ID as a NSString.
Now, I want to open the PromotionDetailViewController with the promotion id as the parameter.
What I have done up to now is,
PromotionDetailViewController *pVC = [[PromotionDetailViewController alloc] initWithPromotionID:promo_id[#"promo_id"]];
[(UINavigationController *)self.window.rootViewController pushViewController:pVC animated:YES];
[(UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController popViewControllerAnimated:YES ];
I am able to receive and read the promo ID in the AppDelegate.m file.
When I run the above code, I get the below error.
MainViewController pushViewController:animated:]: unrecognized
selector sent to instance 0x1459e980
Any help in the right direction is great! I do php and android, but Obj-C is quite different!
UPDATE
Changed the code to this:
PromotionDetailViewController *pvc = [[PromotionDetailViewController alloc] initWithPromotionID:promo_id[#"promo_id"]];
UINavigationController *promoNav =
[[UINavigationController alloc] initWithRootViewController:pvc];
self.window.rootViewController = promoNav;
Now the API call is successful, I am able to see the correct NAV bar, but the app crashes due to the below error:
Terminating app due to uncaught exception 'NSRangeException', reason:
'*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty
array'

(UINavigationController *)self.window.rootViewController it seems that is not a UINavigationController.
To get the correct NavigationController you can do self.navigationController if 'self' is already a child controller of the navigation one.
In obj-c Unrecognized selector means that you are sending a message to an object that does not respond to that, since you are casting it manually with parenthesis, the compiler doesn't complain and thinks is actually a NavgiationController, but isn't.

Related

Issues with rootViewController and Home Screen Quick Actions

I have the below Objective-C code to launch my app with Home Screen Quick Actions:
- (void)applyShortcutItem:(UIApplicationShortcutItem *)shortcutItem
{
ViewController *rootViewController = (ViewController *)[self.window rootViewController];
NSLog(#"Here %# - %#", rootViewController, shortcutItem);
if([shortcutItem.type isEqualToString:#"LaunchMode0"])
{
[rootViewController setShortcutAction:LaunchMode0];
}
else if([shortcutItem.type isEqualToString:#"LaunchMode1"])
{
[rootViewController setShortcutAction:LaunchMode1];
}
}
However, I keep getting runtime errors (unrecognized selected sent to instance) when I try to launch with the quick actions. Notably, it's these two lines where the app seems to trip up:
[rootViewController setShortcutAction:LaunchMode0]; and [rootViewController setShortcutAction:LaunchMode1];
It doesn't seem to like the rootViewController. Technically, the initial View Controller is the Navigation Controller, however the app launches to my main view controller (the app only has two views, the main one, and an about page).
There is more code above that code in my project, but this is the part that's giving me the error-- but let me know if seeing the other code would help (I didn't want the post to be too code heavy).
Thanks so much!
EDIT: as requested, here is the complete NSLog.
2019-09-23 18:18:01.317271-0400 AppName[1719:200993] Here <UINavigationController: 0x108802200> - <UIApplicationShortcutItem: 0x282bd1500; type: Mode1Shortcut, title: Mode 1>
2019-09-23 18:18:01.321819-0400 AppName[1719:200993] -[UINavigationController setShortcutAction:]: unrecognized selector sent to instance 0x108802200
2019-09-23 18:18:01.323462-0400 AppName[1719:200993] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController setShortcutAction:]: unrecognized selector sent to instance 0x108802200'
*** First throw call stack:
(0x2045aa98c 0x2037839f8 0x2044c71c8 0x231033220 0x2045b01d4 0x2045b1e6c 0x102c14af0 0x102c148ec 0x230ffdf90 0x2308cc468 0x2308cd150 0x2308cc224 0x2308d0f24 0x230c012b0 0x206f275d8 0x102fecc78 0x102ff0840 0x206f61040 0x206f60cdc 0x206f61294 0x20453c728 0x20453c6a8 0x20453bf90 0x204536ecc 0x2045367c0 0x20673779c 0x231007c38 0x102c076d0 0x203ffa8e0)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
The problem is this:
ViewController *rootViewController = (ViewController *)[self.window rootViewController];
But you have stated that the root view controller is a UINavigationController. You need to get your ViewController from the nav controller.
UINavigationController *rootViewController = (UINavigationController *)self.window.rootViewController;
ViewController *viewController = (ViewController *)rootViewController.topViewController;
Then update the rest of the code to work on viewController.

"Terminating app due to uncaught exception" getting crash when pushing view controller

Terminating app due to uncaught exception 'NSInvalidArgumentException', > reason: '-[UIViewController setDicSelectListItem:]: unrecognized selector sent to instance 0x10981be30'
I tried comment parameter passing. also tried provide main storyboard.
Below is the code where app getting crash
BilingInfoVC *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"BilingInfoVC"];
vc.dicSelectListItem=_dicSelectListItem;
vc.serviceType=_serviceType;
vc.arrSelect_Addons = [arrTemp mutableCopy];
[self.navigationController pushViewController:vc animated:YES];
I want to pass parameters with instantiate view controller.
Check this:
Is vc really of class 'BilingInfoVC'? If you didn't assign it correctly in IB it's a standard view controller.
You may check it with
NSLog(#"Class: %#", [vc className]);
As second line right after instantination of vc.
Did you set the identifier correctly? A capital letter can make a difference!

Add Value to property on ViewController from AppDelegate

I have the following code:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
[tabBarController performSegueWithIdentifier:#"push_display_incomming_call" sender:self];
This shows me the ViewController I want to see correctly. But now I want to change the property's value of the ViewController is being Segue before it's shown, I'm Trying the following with no success.
incommingCallViewController *mainController = (incommingCallViewController*) tabBarController;
mainController.name.text = #"Eddwn Paz";
This is the stacktrace from xCode Console:
2014-07-10 16:46:09.413 mobile-app[9354:60b] -[OptionsTabBarViewController name]: unrecognized selector sent to instance 0x17552540
2014-07-10 16:46:09.414 mobile-app[9354:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[OptionsTabBarViewController name]: unrecognized selector sent to instance 0x17552540'
Assume that push_display_incomming_call segue presents IncommingCallViewController view controller as modal. So you should use code:
IncommingCallViewController *callVC =
(IncommingCallViewController *)tabBarController.presentedViewController;
callVC.name.text = #"Eddwn Paz";
Remarks:
You receive the error because you try to use tabBarController as instance of incommingCallViewController while it is instance of UITabBarController thus it does not have required name property.

Unrecognized selector sent

I have 1 View Controller and 1 Tab Bar Controller with 2 Navegation Controller.
In my simple View I have one form and then when I click in button "Login" I want to load the first View in my Tab Bar Controller.
With this code works perfect:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
Inicial *telaInicial = [storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
[self presentViewController:telaInicial animated:YES completion:nil];
But I want to send and value to this View "Inicial" and I put this:
telaInicial.email = email.text;
But I got this error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITabBarController setEmail:]: unrecognized selector sent to instance 0x9fdc8f0'
The object telaInicial that you think is an instance of Inicial is actually a UITabBarController therefore you cannot set the email property on it as it doesn't exist.
I think you want something like this...
UITabBarController *tabBarController = [self.storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
UINavigationController *navController = tabBarController.viewControllers[0];
Inicial *telaInicial = navController.topViewController;
telaInicial.email = // blah
It means that there isn't a setEmail method for the telaInicial object. Is that an instance of a subclass you've written? If so, you might be getting the error because you haven't written a setEmail method for it or because you haven't declared the instance variable email as an #property, in which case the setter and getter methods for it would be synthesized automatically by XCode (prior to XCode 4.something, I think you need to synthesize your properties explicitly - after that version, they're automatic).
Try to write class, that will store your data.
You can access to it from AppDelegate (not really good solution, but very fast).

Create UIView on previous UIViewController from another UIViewController

How can I create a UIView on my previous UIViewController after popping the current UIViewController.
On my previous UIViewController I have a function that can be accessed on other UIViewControllers:
-(void)setMovieCompare:(NSString *)_movieName {
NSLog(#"Movie Compare %#",_movieName);
UIView *vw2ndPlayer = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 166)];
[self.view addSubView:vw2ndPlayer];
}
Then on my current UIViewController I have:
VideoPlayerViewController *_VideoPlayerViewController = [[VideoPlayerViewController alloc] initWithNibName:nil bundle:nil];
[_VideoPlayerViewController setMovieCompare:mediaObject.name];
[self.navigationController popViewControllerAnimated:YES];
It is causing me a:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString appendString:]: nil argument'
*** First throw call stack:
(0x31a3e2a3 0x398a297f 0x31a3e1c5 0x31a0d773 0x72461 0x74077 0x33865595 0x7600b 0x7aa6d 0x3390828d 0x3398af81 0x3234c277 0x31a135df 0x31a13291 0x31a11f01 0x31984ebd 0x31984d49 0x3553b2eb 0x3389a301 0x6e89d 0x39cd9b20)
libc++abi.dylib: terminate called throwing an exception
That code crashes because it's trying to read the vc from a nibNamed:nil. Even if you got that working, it wouldn't work. The code isn't changing the VideoPlayerVC that pushed the current vc, it's just allocating a new one (trying to) and changing a view on that new one, which gets released right after that method finishes.
The way to see the presenting view controller in a navigation container is to access self.navigationController.viewControllers.
NSArray *vcs = self.navigationController.viewControllers;
VideoPlayerViewController *previousVC = vcs[MAX(0, vc.count-2)];
[previousVC setMovieCompare ...];
Reaching down the navigation array may not be the best thing, especially of other view controllers can present the current vc. An alternative design is the delegate pattern, where the VideoPlayerVC sets itself as the pushed vs's delegate before pushing.

Resources