Hi and thanks in advance.
I have an application i wrote that uses the new UIApplicationShortcut's on the home screen using 3D touch. The shortcuts work once the app is app, but if the app is closed out the shortcuts do not work on the home screen.
When the application is closed the shortcuts launch the app, but the shortcuts do not work, only the application launches.
here is the two methods I use for the shortcuts.
- (void)setupViewControllers {
// setup the navigation stack
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 480)
{
_navigationController = (UINavigationController *)self.window.rootViewController;
// iPhone 5 and iPod Touch 5th generation: 4 inch screen
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone4
UIStoryboard *iPhone4Storyboard = [UIStoryboard storyboardWithName:@"Main4s" bundle:nil];
UIViewController *initialViewController = [iPhone4Storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
self.myViewController = (ViewController *)_navigationController.topViewController;
self.myViewController.managedObjectContext = self.managedObjectContext;
[self.window makeKeyAndVisible];
}
if (iOSDeviceScreenSize.height == 568)
{
_navigationController = (UINavigationController *)self.window.rootViewController;
// iPhone 5 and iPod Touch 5th generation: 4 inch screen
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone4
UIStoryboard *iPhone4Storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *initialViewController = [iPhone4Storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
self.myViewController = (ViewController *)_navigationController.topViewController;
self.myViewController.managedObjectContext = self.managedObjectContext;
[self.window makeKeyAndVisible];
}
if (self.myViewController){NSLog(@"myViewController is not nil, setupViewControllers");}
else
{
NSLog(@"myViewController is nil, setupViewControllers");//breakpoint inserted here...
}
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
[self setupViewControllers];
// react to shortcut item selections
NSLog(@"A shortcut item was pressed. It was %@.", shortcutItem.localizedTitle);
if([shortcutItem.localizedTitle isEqualToString:@"Scan Tag"])
{
[self.myViewController toggleScanningTapped:nil];
}
if([shortcutItem.localizedTitle isEqualToString:@"Enter Tag"])
{
[self.myViewController manualEntry];
}
if([shortcutItem.localizedTitle isEqualToString:@"Search for a Tag"]){
[self.myViewController SearchSwitch];
[self.myViewController toggleScanningTapped:nil];
}
if([shortcutItem.localizedTitle isEqualToString:@"Just Scan & Copy"]){
[self.myViewController justCopy];
}
if (self.myViewController){NSLog(@"myViewController is not nil, performActionForShortcutItem");}
else
{
NSLog(@"myViewController is nil, performActionForShortcutItem");
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self setupViewControllers];
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
if (url != nil && [url isFileURL]) {
[self.myViewController handleOpenURL:url];
}
if (self.myViewController){NSLog(@"myViewController is not nil, didFinishLaunchingWithOptions");}
else{NSLog(@"myViewController is nil, didFinishLaunchingWithOptions");}
return YES;
}
here is the plist entries...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>com.PALIANTech.SUNYScanner.static1</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Scan Tag</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>Add tag to DB</string>
<key>UIApplicationShortcutItemIconFile</key>
<string>barcode.png</string>
</dict>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>com.PALIANTech.SUNYScanner.static2</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Enter Tag</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>Manually add tag to DB</string>
<key>UIApplicationShortcutItemIconFile</key>
<string>ManualEntry.png</string>
</dict>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>com.PALIANTech.SUNYScanner.static3</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Search for a Tag</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>Scan a tag to search for</string>
<key>UIApplicationShortcutItemIconFile</key>
<string>search.png</string>
</dict>
</array>
</plist>
Any help or suggestions would be greatly appreciated.
The reason is that when your app starts freshly self.myViewController
is still nil
at the time when you check your short cut items in performActionForShortcutItem
and didFinishLaunchingWithOptions
. So nothing happens.
To fix this you would have to instantiate myViewController
and add it to the navigation stack when the app is opened via a shortcut.
EDIT
Here is a (stripped down) version that works:
AppDelegate
@interface AppDelegate ()
@property ViewController *viewController;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self setupViewControllers];
return YES;
}
- (void)setupViewControllers {
self.viewController = [[ViewController alloc] init];
self.viewController.view.backgroundColor = [UIColor lightGrayColor];
self.viewController.label.text = @"Normal Launch";
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
[self setupViewControllers];
if([shortcutItem.localizedTitle isEqualToString:@"Scan Tag"]) {
self.viewController.label.text = @"Shortcut: Scan Tag";
}
if([shortcutItem.localizedTitle isEqualToString:@"Enter Tag"]) {
self.viewController.label.text = @"Shortcut: Enter Tag";
}
if([shortcutItem.localizedTitle isEqualToString:@"Search for a Tag"]) {
self.viewController.label.text = @"Shortcut: Search Tag";
}
if([shortcutItem.localizedTitle isEqualToString:@"Just Scan & Copy"]) {
self.viewController.label.text = @"Shortcut: Scan & Copy Tag";
}
}
@end
The ViewController
class is a plain UIViewController
subclass that just has a label for demonstration purposes.
I have tested the shortcuts with an app that was in the background and with the app completely removed from memory. Both worked as intended.
UPDATE
If you are using a ViewController from a storyboard you have to initialize it like this:
- (void)setupViewControllers {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
self.viewController = (ViewController *)[storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
...
}
Don't forget to set the ViewController's identifier in your storyboard: