在Obj-C中实现3D Touch主屏快捷方式

25

我的所有应用程序目前都是用Obj-C编写的。链接 https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545 是使用Swift编写的实现带有3D Touch的主屏幕快捷方式的示例代码。有没有人找到了Obj-C文档,这样我就不必查看我的AppDelegate并将其全部翻译?

更新:

在Info.plist中添加了所有快捷方式后,我在AppDelegate.m中添加了以下内容:

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
    UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;

    NSLog(@"%@", shortcutItem.type);
    if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayerRequest"]) {
        Requests *gonow = [[Requests alloc] init];

        [nav pushViewController:gonow animated:YES];

    }
    if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayer"]) {

      PrayerStats *controller = [[PrayerStats alloc] init];
        [nav pushViewController:controller animated:YES];

    }

    if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addFast"]) {

      FastStats *controller1 = [[FastStats alloc] init];
        [nav pushViewController:controller1 animated:YES];

    }

    if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addStudy"]) {

      StudyStats *controller2 = [[StudyStats alloc] init];
        [nav pushViewController:controller2 animated:YES];

    }
   }

这使得它能够正常工作,而无需添加其他方法或在didFinishLaunchingWithOptions中添加任何内容。

5个回答

25

用户可以通过快捷操作从两个状态打开应用程序。

简而言之 无论应用程序在何种状态下执行快速操作,您总是执行相同的操作,这就是为什么只需要覆盖application:performActionForShortcutItem:completionHandler:。如果您想要执行不同的操作,则需要在两个位置处理它们,否则只需覆盖即可。

  • 一个状态是:当应用程序被杀死或未在后台运行时,我们会在启动时获取快捷方式信息。

  • 另一个状态是:当应用程序在后台运行时,我们在新的应用程序代理方法中获取快捷方式信息。

要在后台处理这些快捷操作,请在应用程序委托上覆盖此方法:

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler

而且不会在您的设备后台运行(被关闭)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
或者
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

您应该检查应用程序是否由快速操作启动:

UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];

(相关苹果文档链接) 引用官方Apple文档

你需要确保系统有条件地调用此方法,具体取决于你的应用程序启动方法(application:willFinishLaunchingWithOptions:或application:didFinishLaunchingWithOptions:)是否已经处理了快速操作调用。 当用户选择应用程序的快速操作并且应用程序启动而不是激活时,系统将调用启动方法(在调用此方法之前)。

请求的快速操作可能会使用与应用程序正常启动时不同的代码路径。例如,假设您的应用程序通常启动以显示视图A,但是响应需要视图B的快速操作而启动了应用程序。为处理此类情况,请在应用程序启动时检查应用程序是否通过快速操作启动。在您的application:willFinishLaunchingWithOptions:或application:didFinishLaunchingWithOptions:方法中通过检查UIApplicationLaunchOptionsShortcutItemKey启动选项键来执行此检查。 UIApplicationShortcutItem对象可作为启动选项键的值。

如果发现您的应用确实是使用快速操作启动的,请在启动方法中执行请求的快速操作,并从该方法返回NO值。当您返回NO值时,系统将不会调用application:performActionForShortcutItem:completionHandler:方法。


我有什么遗漏吗?当我在didFinishLaunching中添加最后一行代码时,我得到了未使用的项shortcutItem。我需要在其他地方添加吗? - user717452
你在设置完shortcutItem后有使用它吗? - Keller
@Keller 不是的,因为这个答案不是我写的,是别人写的,我只是好奇为什么它在里面。只需添加 performActionForShortcutItem 代码即可执行我在信息中添加的快捷方式,由于 Nicolas 在他的答案中没有其他地方提到它,所以我很好奇为什么需要它。 - user717452
1
@user717452,请查看更新后的答案,其中包含了苹果文档的引用。如果您不想处理不同的流程,这并不是必需的。 - Nicolas S
1
@user717452 无论应用程序处于何种状态,您总是在执行相同的操作。因此,如果您想要执行不同的操作,则需要在这两个位置处理它们;否则,只需覆盖即可。我已经为您的问题添加了适当的答案。 - Nicolas S
显示剩余8条评论

4

实现以下3个简单步骤:

步骤1:AppDelegate类中编写以下方法以配置动态快捷方式。

注意:如果您希望它是静态的,则可以在info.plist中配置快捷方式项。 (参见苹果文档。

/**
 *  @brief config dynamic shortcutItems
 *  @discussion after first launch, users can see dynamic shortcutItems
 */
- (void)configDynamicShortcutItems {
    // config image shortcut items
    // if you want to use custom image in app bundles, use iconWithTemplateImageName method
    UIApplicationShortcutIcon *shortcutSearchIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeSearch];
    UIApplicationShortcutIcon *shortcutFavoriteIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeFavorite];

    UIApplicationShortcutItem *shortcutSearch = [[UIApplicationShortcutItem alloc]
                                                 initWithType:@"com.sarangbang.QuickAction.Search"
                                                 localizedTitle:@"Search"
                                                 localizedSubtitle:nil
                                                 icon:shortcutSearchIcon
                                                 userInfo:nil];

    UIApplicationShortcutItem *shortcutFavorite = [[UIApplicationShortcutItem alloc]
                                                 initWithType:@"com.sarangbang.QuickAction.Favorite"
                                                 localizedTitle:@"Favorite"
                                                 localizedSubtitle:nil
                                                 icon:shortcutFavoriteIcon
                                                 userInfo:nil];


    // add all items to an array
    NSArray *items = @[shortcutSearch, shortcutFavorite];

    // add the array to our app
    [UIApplication sharedApplication].shortcutItems = items;
}

第二步:AppDelegate类的application didFinishLaunchingWithOptions方法中,写下面的代码。

    // UIApplicationShortcutItem is available in iOS 9 or later.
        if([[UIApplicationShortcutItem class] respondsToSelector:@selector(new)]){

            [self configDynamicShortcutItems];

            // If a shortcut was launched, display its information and take the appropriate action
            UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKeyedSubscript:UIApplicationLaunchOptionsShortcutItemKey];

            if(shortcutItem)
            {
                // When the app launch at first time, this block can not called.
                //App launch process with quick actions
                [self handleShortCutItem:shortcutItem];
            }else{
                // normal app launch process without quick action
            }

        }

步骤 3 :AppDelegate 类中编写以下委托方法和完成处理程序。

/*
 Called when the user activates your application by selecting a shortcut on the home screen, except when
 application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`.
 You should handle the shortcut in those callbacks and return `false` if possible. In that case, this
 callback is used if your application is already launched in the background.
 */

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{

    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;

    NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;

    NSString *shortcutSearch = [NSString stringWithFormat:@"%@.Search", bundleId];
    NSString *shortcutFavorite = [NSString stringWithFormat:@"%@.Favorite", bundleId];

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];


    if ([shortcutItem.type isEqualToString:shortcutSearch]) {
        handled = YES;

        SecondViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"secondVC"];

        self.window.rootViewController = vc;

        [self.window makeKeyAndVisible];

    }

    else if ([shortcutItem.type isEqualToString:shortcutFavorite]) {
        handled = YES;

        ThirdViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"thirdVC"];

        self.window.rootViewController = vc;

        [self.window makeKeyAndVisible];
    }


    return handled;
}

3

如果您查看苹果提供的示例代码,您会发现他们建议您编写一个处理快捷方式项目的方法,以便您可以在以下三个位置处理它:

  • application:performActionForShortcutItem,
  • application:didFinishLaunchingWithOptions
  • willFinishLaunchingWithOptions

我所做的一个示例是:

- (BOOL)handleShortCutItem:(UIApplicationShortcutItem *)shortcutItem {
    BOOL handled = NO;

    if (shortcutItem == nil) {
        return handled;
    }

    if ([shortcutItem.type isEqualToString:kFavoritesQuickAction]) {
        handled = YES;
    } 

    if (handled) {
        // do action here
    }

    return handled;
}

那么你只需要在获取快捷方式项的任何位置调用此方法。这应该可以帮助你顺利完成任务!


看到更新的原帖...似乎并不需要这么多代码了,毕竟? - user717452
这里的回应已经非常晚了,但是这种处理快捷方式的方式是苹果建议采用的方式。我相信他们提到了开发人员有责任处理可能发生的多种情况,而我的答案展示了这一点。您还可以在他们的示例代码中看到他们如何处理它:https://developer.apple.com/library/ios/samplecode/ApplicationShortcuts/Listings/ApplicationShortcuts_AppDelegate_swift.html - sdoowhsoj

1
我制作了一个针对主屏幕快速操作的Objective-C演示项目。 3D touch home quick action demo : https://github.com/dakeshi/3D_Touch_HomeQuickAction 该演示项目实现了静态快速操作,避免在首次启动应用程序之前出现意外情况而不需要Info.plist文件。您可以轻松地将其更改为动态快速操作。
正如苹果文档中所述,您可以在application:didFinishLaunchingWithOptions:方法中处理快速操作。在这种情况下,您应该返回NO以阻止调用application:performActionForShortcutItem:completionHandler:方法。

0

它适用于Swift 3和4(仅限主屏幕快捷方式)

//Add plist items as show in image and write following method in Appdelegate
//3D Touch Method shortcuts from home screen

func application(_ application: UIApplication, performActionFor shortcutItem:UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {

if shortcutItem.type == "Share" {
    //handle action Share
    let alert = UIAlertController(title: "3D touch Share", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.window?.rootViewController?.present(alert,animated: true,completion: nil)
    completionHandler(true)
   } else if shortcutItem.type == "Logout" {

    //handle action Type02
    let alert = UIAlertController(title: "3D touch Logout", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    self.window?.rootViewController?.present(alert,animated: true,completion: nil)
    completionHandler(true)
   } else {
    completionHandler(false)
  }

 }

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接