skip to Main Content

I am very new to the iOS Application development and I have been following tutorials to build my career . So starting with I am trying to Implement Static Quick Actions in Objective C as per client project . I was able to add the keys and got the options while pressing the icon . But when I press the Quick Actions nothing happens and it just launches the Application. I have researched a lot and I tried but in vain. Below is the Appdelegate code which I have written:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    BOOL shouldPerformAdditionalDelegateHandling = YES;
    
    
    // Check API availiability
    // UIApplicationShortcutItem is available in iOS 9 or later.
    if([[UIApplicationShortcutItem class] respondsToSelector:@selector(new)]){
        NSLog(@"HERE");
        //  [self configDynamicShortcutItems];
        
        // If a shortcut was launched, display its information and take the appropriate action
        UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKeyedSubscript:UIApplicationLaunchOptionsShortcutItemKey];
        
        if(shortcutItem)
        {
            NSLog(@"shortcut launch");
            // When the app launch at first time, this block can not called.
            
            [self handleShortCutItem:shortcutItem];
            
            // This will block "performActionForShortcutItem:completionHandler" from being called.
            shouldPerformAdditionalDelegateHandling = NO;
            
            
        }else{
            NSLog(@"normal launch");
            // normal app launch process without quick action
            
            // [self launchWithoutQuickAction];
            
        }
        
    }else{
        
        // Less than iOS9 or later
        
        //  [self launchWithoutQuickAction];
        
    }
    
    
    return shouldPerformAdditionalDelegateHandling;
}


- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{
    NSLog(@"performActionForShortcutItem");
    
    BOOL handledShortCutItem = [self handleShortCutItem:shortcutItem];
    
    completionHandler(handledShortCutItem);
}


/**
 *  @brief handle shortcut item depend on its type
 *
 *  @param shortcutItem shortcutItem  selected shortcut item with quick action.
 *
 *  @return return BOOL description
 */
- (BOOL)handleShortCutItem : (UIApplicationShortcutItem *)shortcutItem{
    
    BOOL handled = NO;
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    
    
    if ([shortcutItem.type isEqualToString:@"PlayMusic"]) {
        handled = YES;
        NSLog(@"Play");
        
        secondview *vc = [storyboard instantiateViewControllerWithIdentifier:@"second"];
        
        self.window.rootViewController = vc;
        
        [self.window makeKeyAndVisible];
        
    }
    
    else if ([shortcutItem.type isEqualToString:@"StopMusic"]) {
        handled = YES;
        NSLog(@"Stop");
        //        ThirdViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"thirdVC"];
        //
        //        self.window.rootViewController = vc;
        
        [self.window makeKeyAndVisible];
    }
    
    
    return handled;
}

However I can see the Quick Action items when I deep press the home icon but on clicking that no action happens. I check the key in info.plist and its the same .
Quick Actions

Below is the info.plist for adding Static Actions

<key>UIApplicationShortcutItems</key>
<array>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypePlay</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Play</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Start playback</string>
        <key>UIApplicationShortcutItemType</key>
        <string>PlayMusic</string>
    </dict>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypePlay</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>STOP</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Stop playback</string>
        <key>UIApplicationShortcutItemType</key>
        <string>StopMusic</string>
    </dict>

Can some one please help where I am doing wrong?

2

Answers


  1. since iOS(13.0, *) AppDelegate handles its own UIWindow via SceneDelegate‘s and so the method

    @implementation AppDelegate
    
    -(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
    {
        // here shortcut evaluation below ios(13.0)
    }
    
    @end
    

    is only invoked on iPhones or iPads with iOS lower Version 13.0

    So to make it work in iOS(13.0,*) and above you need to implement it in SceneDelegate with a slightly different name, see below.. (matt was right!)

    @implementation SceneDelegate
    
    -(void)windowScene:(UIWindowScene *)windowScene performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
        // here shortcut evaluation starting with ios(13.0)
        NSLog(@"shortcutItem=%@ type=%@",shortcutItem.localizedTitle, shortcutItem.type);
    }
    
    @end
    

    PS: The Apple Example Code for Quick Actions in swift is bogus when you assume you can use it as is in iOS(13.0,*) because it is written for versions earlier iOS < 13.0

    EDIT: as asked, here in full beauty for iOS >= 13.0

    @interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
    @property (strong, nonatomic) UIWindow * window;
    @end
    

    and

    -(void)windowScene:(UIWindowScene *)windowScene performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
        /* //go to Info.plist open as Source Code, paste in your items with folling scheme
        <key>UIApplicationShortcutItems</key>
        <array>
            <dict>
                <key>UIApplicationShortcutItemIconType</key>
                <string>UIApplicationShortcutIconTypePlay</string>
                <key>UIApplicationShortcutItemTitle</key>
                <string>Play</string>
                <key>UIApplicationShortcutItemSubtitle</key>
                <string>Start playback</string>
                <key>UIApplicationShortcutItemType</key>
                <string>$(PRODUCT_BUNDLE_IDENTIFIER).Start</string>
            </dict>
            <dict>
                <key>UIApplicationShortcutItemIconType</key>
                <string>UIApplicationShortcutIconTypePlay</string>
                <key>UIApplicationShortcutItemTitle</key>
                <string>STOP</string>
                <key>UIApplicationShortcutItemSubtitle</key>
                <string>Stop playback</string>
                <key>UIApplicationShortcutItemType</key>
                <string>$(PRODUCT_BUNDLE_IDENTIFIER).Stop</string>
            </dict>
        </array>
         */
        
        // may look complex but this is 100% unique
        // which i would place $(PRODUCT_BUNDLE_IDENTIFIER). in front of types in Info.plist
        NSString *devIdent = [NSString stringWithFormat:@"%@.",NSBundle.mainBundle.bundleIdentifier];
        
        if ([shortcutItem.type isEqualToString:[devIdent stringByAppendingString:@"Start"]]) {
            completionHandler([self windowScene:windowScene byStoryBoardIdentifier:@"startview"]);
            
        } else if ([shortcutItem.type isEqualToString:[devIdent stringByAppendingString:@"Stop"]]) {
            completionHandler([self windowScene:windowScene byStoryBoardIdentifier:@"stopview"]);
    
        } else {
            NSLog(@"Arrgh! unrecognized shortcut '%@'", shortcutItem.type);
        }
        //completionHandler(YES);
    }
    
    -(BOOL)windowScene:(UIWindowScene *)windowScene byStoryBoardIdentifier:(NSString *)identifier {
        // idear is to return NO if build up fails, so we can startup normal if needed.
        UIStoryboard *story = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        if (story!=nil) {
            UIViewController *vc = [story instantiateViewControllerWithIdentifier:identifier];
            if (vc!=nil) {
                if (_window==nil) _window = [[UIWindow alloc] initWithWindowScene:windowScene];
                _window.rootViewController = vc;
                
                // .. OR following code..
                //[_window.rootViewController presentViewController:vc animated:YES completion:^{ }];
                //[_window makeKeyAndVisible];
                
                // should be success here..
                return YES;
            }
        }
        // no success here..
        return NO;
    }
    

    You can do also other things than instantiate a ViewController from Storyboard. In example you could switch a property or something similar.

    Login or Signup to reply.
  2. Sorry being too late. Further research about home quick actions showed me the following conclusions after discussing with major developers . The following points which needed to be followed while integrating HomeQuickActions are :

    1. Most Important point for every developer: Home quick actions(short cut items on clicking app icon) are definitely OS and hardware based (supported only from iOS 13). Apple documents. It means before iOS 13 no device will show app short cut items even if they have Haptic Touch / 3D Touch. iOS 13 and above is a mandatory requirement.(Checked in Simulator for all iPhone, need to test in real device with older phones)

    Both 3D touch enable and non-3D touch enabled devices support this feature through force-touch or long-press depending on device capabilities if they are capable of running iOS 13 or above.

    1. So for App short cuts to work the iOS devices must be having iOS 13 for sure and the hardware compatibility is also required which means the devices must be having iOS 13 and above for App short cuts to work. For iPhone 5S, iPhone 6 owners: iOS 13 won’t be compatible anymore.

    2. Since Apple has replaced 3D Touch hardware with Haptic Touch , the newer iPhones from iPhone XR will have only Haptic Touch . Old devices after SE(1 st generation, iPhone 6 series till iPhone X ) have 3D Touch hardware. Haptic Touch is a software OS dependent which uses finger pressed area and 3D Touch is a hardware dependent which uses a specific sensor between screen.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search