3D Touch for Shortcuts Crashes - ios

My app is a single-view NavigationController as a root view controller style app. In it, I have a few different shortcut items for using 3D Touch. I have them all set up in the Info.plist fine (I've done this before with a Tab Bar app and it worked fine), but it crashes every time an shortcut action is pressed. Here is my the code used in AppDelegate in Obj-C.
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
UINavigationController *nav = (UINavigationController *) self.theMainView.view;
NSLog(#"%#", shortcutItem.type);
if ([shortcutItem.type isEqualToString:#"com.316apps.Fritch.inviteFriends"]) {
ImagePicker *vimeo= [[ImagePicker alloc] init];
[nav pushViewController:vimeo animated:YES];
}
if ([shortcutItem.type isEqualToString:#"com.316apps.Fritch.viewAlerts"]) {
NewsViewController *dvController8 = [[NewsViewController alloc] initWithNibName:#"NewsViewController" bundle:[NSBundle mainBundle]];
[nav pushViewController:dvController8 animated:YES];
}
if ([shortcutItem.type isEqualToString:#"com.316apps.Fritch.viewDirectory"]) {
DirectoryViewController *dvController8 = [[DirectoryViewController alloc] init];
[nav pushViewController:dvController8 animated:YES];
}
}
Crash Log:
com.316apps.Fritch.viewDirectory
2017-01-19 22:44:23.305906 Fritch[3956:925348] -[UILayoutContainerView pushViewController:animated:]: unrecognized selector sent to instance 0x101837530
2017-01-19 22:44:23.306768 Fritch[3956:925348] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILayoutContainerView pushViewController:animated:]: unrecognized selector sent to instance

UINavigationController *nav = (UINavigationController *) self.theMainView.view;
The reason of crashing is you are getting the view, not ViewController. So self.theMainView.view cannot convert to UINavigationController. If your self.theMainView is correct, fix that crash by using:
UINavigationController *nav = (UINavigationController *) self.theMainView;

Related

iOS 'NSInternalInconsistencyException', reason: 'UICollectionViewFlowLayout internal error

I have a collection view inside self-sizing tableview. When user tap on collection view, I present another view.
I can still present that view in portrait orientation. But when I rotate to landscape, I got this error and crash. How shall I do?
2017-01-23 16:52:16.448417 SWEET Mini[1638:647130] * Assertion
failure in -[_UIFlowLayoutSection
computeLayoutInRect:forSection:invalidating:invalidationContext:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3600.6.22/UIFlowLayoutSupport.m:823
2017-01-23 16:52:16.451537 SWEET Mini[1638:647130] * Terminating app
due to uncaught exception 'NSInternalInconsistencyException', reason:
'UICollectionViewFlowLayout internal error'
I just present another view like this.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
browser.zoomPhotosToFill = NO;
[browser setCurrentPhotoIndex:(indexPath.row)];
browser.enableSwipeToDismiss = YES;
UINavigationController *browseNav = [[UINavigationController alloc] initWithRootViewController:browser];
if ([[AppDelegate instance].window.rootViewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController *) [AppDelegate instance].window.rootViewController;
[nav presentViewController:browseNav animated:YES completion:nil];
}
else if ([[AppDelegate instance].window.rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *) [AppDelegate instance].window.rootViewController;
[tab presentViewController:browseNav animated:YES completion:nil];
}
}
I had the same issue with the same error message. Turns out, it's only happening on the simulator, everything works fine on real device.

Navigating from Appdelegate when push message received

Currently this is how my method loooks
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSString *screenNo =[userInfo objectForKey:#"screen"];
}
Based on the screenNo I would like to navigate to different view controllers. But I couldn't do as most of the answers given below.
Reason is that my root view is not navigation control, so I couldn't segue. It crashes the app.
when push message arrives didReceiveRemoteNotification is called and I could see the content of the message too. But it doesn't get navigated using the methods shown here.
[self.window makeKeyAndVisible];
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"galleryViewController2"];
[(UINavigationController *)self.window.rootViewController pushViewController:vc animated:YES];
this is the exception
2014-07-21 18:06:53.709 Proitzen Rest[993:60b] -[RESTSecondViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14e26270
2014-07-21 18:06:53.712 Proitzen Rest[993:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RESTSecondViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14e26270'
*** First throw call stack:
(0x2f480fd3 0x3a021ccf 0x2f484967 0x2f483253 0x2f3d27b8 0xff93b 0x31eb3b29 0x31eb37fb 0x31dbb05f 0x31e6d377 0x31d1c6f5 0x31c9555b 0x2f44c2a5 0x2f449c49 0x2f449f8b 0x2f3b4f0f 0x2f3b4cf3 0x342da663 0x31d0016d 0x157e69 0x3a52eab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Thanks for your time in advance.
Did you try something like this?
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"galleryViewController2"];
self.window.rootViewController = vc;
Instead of pushing your new controller (it crashes because to push you need a navigation controller) you can replace current controller with the new one.
Please, take in account that you can not pop to the original controller (if you need to get back, you need a navigation)
You're trying to push a UIViewController with a UIViewController. This is not possible. You must have a UINavigationController in your app hierarchy.
You can also just set the rootViewController:
[self.window setRootViewController: newViewController];
make sure you call this method before trying to present any view controller.
[self.window makeKeyAndVisible];
You can't navigate using push and Pop from APPDelegate if you need to navigate from appDelegate to a file, Segues won't help either then You would need to load it first in your window and then make it Visible such as..
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSString *screenNo =[userInfo objectForKey:#"screen"];
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
firstViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"firstVC"];
// First item in array is bottom of stack, last item is top.
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}
This is what finally saved me. placed it inside didReceiveRemoteNotification method.
NSLog(#"User wanna navigate");
[self.window makeKeyAndVisible];
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"moreTableViewController"];
self.window.rootViewController = vc;
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
UIViewController *evc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"eventsViewController"];
[navController.visibleViewController.navigationController pushViewController:evc animated:YES];

Changing UIViewController from AppDelegate on ios for push notification

When a user gets a push notification, I want the app to open up to a certain UIViewController. I'm in xCode 5 with storyboard.
I think my code is close but it is throwing an error
Here is the method in AppDelegate
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UINavigationController *nav = (UINavigationController *)self.window.rootViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
RewardList *vc = (RewardList *)[storyboard instantiateViewControllerWithIdentifier:#"RewardList"];
[nav pushViewController:vc animated:YES];
}
It errors out on the [nav pushViewController:vc animated:YES]; I'm not quite sure what is going on. Can someone help shed light on this issue?
Here is the error:
-[SplashViewController pushViewController:animated:]: unrecognized selector sent to instance 0x1f862630 2013-12-12 17:58:28.719 appName[473:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SplashViewController pushViewController:animated:]: unrecognized selector sent to instance 0x1f862630'
EDIT:
The app root view controller is SplashNavigationController which is a UIViewController. From there I have a UITabBarController. Inside of that on my 3rd tab, is RewardList which is also a UIViewController. I need to go from whatever the current view is, to my 3rd tab, the RewardList tab.
I'm finding a lot of posts on this, but nothing seems to work in my case.
The first thing I would do to fix this is change the structure so the tab bar controller is the root view controller of the window. If you want your splash screen to come up first, then present that modally (with no animation) from the viewDidAppear method in the controller in the first tab. When you're done with that screen, you can just dismiss it, and you'll be in the first controller. If you make that change, then doing what you want in the app delegate will be simple,
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
tbc.selectedIndex = 2;
}
I would also suggest that you study Apple's "View Controller Programming Guide for iOS" to learn about view controllers and their life cycle.
It sounds like your root view controller is a view controller of the class SplashViewController. Is SplashViewController a subclass of UINavigationController? It has to be, or you'll get that error.
There are some ways to get top most view controller on this thread.
https://stackoverflow.com/a/23603265/
I like this code because it's very simple.
https://stackoverflow.com/a/23603265/1971596
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
And then you just present view controller from top most view controller.

performSegueWithIdentifier NSInvalidArgumentException after call from AppDelegate

Hey together,
I am calling a void with some parameters from the AppDelegate on my main view.
This is done if a push notification is received:
MainViewController *mainView = [[MainViewController alloc] init];
[mainView showPushView:pushDataObject];
The called void # the MainView doing some data operating stuff and after that it should load the pushView:
- (void)showPushView: (PFObject *)pushDataObject {
NSLog(#"Push Data object transfered %#", pushDataObject);
pushItem = pushDataObject;
//All working fine to this point
[self performSegueWithIdentifier:#"showPushObject" sender:self];
}
Now the problem is that the app is crashing at [self performSegueWithIdentifier:#"showPushObject" sender:self]; with this Error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'Receiver (<MainViewController: 0x145b80e0>) has no segue with identifier 'showPushObject''
*** First throw call stack:
(0x2e51fe83 0x3887c6c7 0x30f656d9 0xbeb11 0xb2a23 0x1745f7 0x38d610c3 0x38d610af 0x38d639a9 0x2e4ea5b1 0x2e4e8e7d 0x2e453471 0x2e453253 0x3318d2eb 0x30d08845 0xafecd 0x38d75ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
I think that there is a problem because I call the void from the AppDelegate, am I right?
Those anyone know a fix for that problem?
Thanks a lot!
Best regards from Germany :)
P.S. If I call [self performSegueWithIdentifier:#"showPushObject" sender:self]; with a button or something on the MainViewController all working fine... :/
In order for the segue to work, you need to have the storyboard loaded in the mainView when you start it that way. Try instead something like this:
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *firstViewController = [storyboard instantiateViewControllerWithIdentifier:#"kYourMainViewControllerIdentifier"];
self.window.rootViewController = firstViewController;
[self.window makeKeyAndVisible];
Remember to give an identifier to your root view controller and change it in this piece of code.
Your problem is this line:
MainViewController *mainView = [[MainViewController alloc] init];
because it means that the mainView instance doesn't have a storyboard (so it can't have any segues).
When you run it from a button the controller instance must have been created from a storyboard.
So, to fix, load the storyboard and instantiate mainView from it. Then the segue will work.
UIStoryboard *storyboard4Inch = [UIStoryboard storyboardWithName:#"Storyboard4Inch" bundle:nil];
UIViewController *mainViewController = [storyboard4Inch instantiateViewControllerWithIdentifier:#"MainViewController"];
[mainViewController showPushView:pushDataObject];

'NSInvalidArgumentException' on UILocalNotifcation Load

When loading my application from a local notification I am trying to read its payload. To do so I have the following code:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Loading Stuff
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
[(UITabBarController *)self.window.rootViewController setSelectedIndex:1];
UINavigationController *nav = [[(UITabBarController *)self.window.rootViewController viewControllers] objectAtIndex:1];
IMTRewardsViewController *rvc = [storyboard instantiateViewControllerWithIdentifier:#"rewardsView"];
[rvc loadPushNotification:localNotif];
[nav pushViewController:rvc animated:NO];
}
return YES;
}
IMTRewardsController.h:
-(NSDictionary *)loadPushNotification:(UILocalNotification *)notification;
IMTRewardsController.m:
- (NSDictionary *)loadPushNotification:(UILocalNotification *)notification
{
NSLog(#"%#",notification.userInfo);
return notification.userInfo;
}
When I load my application from a local notification I receive the following error:
<Error>: -[UIViewController loadPushNotification]: unrecognized selector sent to instance 0x14e70b30
<Error>: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController loadPushNotification]: unrecognized selector sent to instance 0x14e70b30'
Any idea as to how to fix this issue and keep it from cropping up in the future?
There error indicates the view controller you've pulled back is only a UIViewController, and not a IMTRewardsViewController like you're expecting. Are you sure you set the custom class property to that type in the storyboard?
You might need to cast it first. The storyboard returns an UIViewController
IMTRewardsViewController *rvc = (IMTRewardsViewController *)[storyboard instantiateViewControllerWithIdentifier:#"rewardsView"];

Resources