【问题标题】:3D Touch Home Shortcuts In Obj-CObj-C 中的 3D Touch 主页快捷方式
【发布时间】:2015-12-14 12:58:50
【问题描述】:

我所有的应用程序目前都是用 Obj-C 编写的。使用 3D Touch 实现主屏幕快捷方式的示例代码链接 https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545 完全用 Swift 编译。任何人都遇到过 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 添加任何内容。

【问题讨论】:

    标签: ios objective-c swift ios9 3dtouch


    【解决方案1】:

    它适用于 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)
      }
    
     }
    

    【讨论】:

      【解决方案2】:

      实施以下 3 个简单步骤:

      第一步:AppDelegate类中编写如下方法来配置动态快捷方式。

      注意:如果您希望它是静态的,您可以在 info.plist 中配置快捷方式项目。 (参考Apple documentation.

      /**
       *  @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;
      }
      

      第 2 步:AppDelegateapplication 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;
        }
        

        然后,您只需在获得快捷方式项的任何地方调用此方法。这应该可以帮助您一路走好!

        【讨论】:

        • 查看更新的 OP...毕竟,似乎不需要很多这样的代码?
        • 在这里回复太晚了,但这种处理快捷方式的方式是 Apple 建议的处理方式。我相信他们提到,开发人员有责任处理我的回答显示的多种可能发生的情况。您还可以在示例代码中看到他们是如何处理它的:developer.apple.com/library/ios/samplecode/ApplicationShortcuts/…
        【解决方案4】:

        我为主屏幕快速操作制作了一个 Objective-c 演示项目。

        3D touch home quick action demo : https://github.com/dakeshi/3D_Touch_HomeQuickAction

        Demo 项目实现了没有 Info.plist 文件的静态快速操作,以避免在首次启动应用程序之前出现不必要的情况。 您可以轻松地将其更改为动态快速操作。

        正如苹果文档中提到的,您可以在 application:didFinishLaunchingWithOptions: 方法中处理快速操作。在这种情况下,您应该返回 NO 以阻止调用 application:performActionForShortcutItem:completionHandler: 方法。

        【讨论】:

          【解决方案5】:

          用户可以在两种状态下通过快速操作打开应用。

          TL;DR 无论快速操作完成时应用程序处于何种状态,您总是在做同样的事情,这就是为什么您只需要覆盖application:performActionForShortcutItem:completionHandler: 因此,如果您想做不同的事情,那么您会想要处理它们这两个地方,如果不是,那么只需覆盖就足够了。

          • 一个是如果应用程序被终止或未在后台运行,我们会在启动时获取快捷方式信息。

          • 另一个是如果应用程序在后台运行,我们会在新的应用程序委托方法上获取快捷方式信息。

          要在后台处理这些快速操作快捷方式,您需要在 App Delegate 上覆盖此方法:

          - (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];
          

          (Link to related Apple Documentation) 引用自 Apple 官方文档

          确保系统调用此方法是您的责任 有条件地,取决于您的应用程序是否启动 方法(应用程序:willFinishLaunchingWithOptions:或 application:didFinishLaunchingWithOptions:) 已经处理了一个 快速操作调用。 系统调用启动方法(之前 调用此方法)当用户为您的应用选择快速操作时 并且您的应用会启动而不是激活。

          请求的快速操作可能使用不同于 那些在您的应用启动时以其他方式使用的。例如,说你的应用 通常启动以显示视图 A,但您的应用是在 响应需要查看 B 的快速操作。要处理此类情况, 在启动时检查您的应用程序是否正在通过快速启动 行动。在您的 应用程序:willFinishLaunchingWithOptions:或 application:didFinishLaunchingWithOptions: 方法通过检查 UIApplicationLaunchOptionsShortcutItemKey 启动选项键。这 UIApplicationShortcutItem 对象可用作 启动选项键。

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

          【讨论】:

          • 我错过了什么吗?当我在 didFinishLaunching 中输入最后一行代码时,我得到了未使用的项目快捷方式项。我需要把它放在其他地方吗?
          • 嗯,你是在设置后使用shortcutItem吗?
          • @Keller 不,因为我没有写这个答案,其他人写了,只是好奇它为什么在那里。只需添加 performActionForShortcutItem 代码,我就可以执行我在 info 中添加的快捷方式,而且由于 Nicolas 在他的答案中没有其他任何地方,所以很好奇为什么需要它。
          • @user717452 从苹果文档中看到更新的答案,如果您不想处理不同的流程,则没有必要。
          • @user717452 无论快速操作完成时应用程序处于何种状态,您总是在做同样的事情。所以如果你想做不同的事情,那么你会想在这两个地方处理它们,如果不是那么只是覆盖就足够了。我已为您的问题添加了正确答案。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多