【问题标题】:iOS app launch due to NSUserActivity. How do access that object?由于 NSUserActivity,iOS 应用程序启动。如何访问该对象?
【发布时间】:2015-08-24 21:46:23
【问题描述】:

所以目前测试了一些ios9 beta 功能,但是NSUserActivity 类已经出一段时间了,用于切换。

基本上就是这样。当应用程序启动到 NSUserActivity 时,我可以看到 launchOptions 有一个键集。

    NSDictionary *userActivityKey = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

基本上该方法永远不会被调用。

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler

这是有道理的,因为应用程序只是由于活动而被打开。 但令我不解的是这一点。

当我检查启动选项时,我无法访问NSUserActivity。显然操作系统会为您创建该对象?

你们中有人处理过这个问题吗?

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    你不应该这样做。你应该从-(BOOL)application:didFinishLaunchingWithOptions:返回YES,然后-(BOOL)application:continueUserActivity:restorationHandler也会被调用。 Apple docs say:

    如果应用程序无法处理 URL 资源或继续用户活动,则返回 NO,否则返回 YES。

    【讨论】:

    • 致对我投反对票的人:我有你认为我错了,请解释一下!
    • 我没有投反对票,但我已经尝试过了,不幸的是 -(BOOL)application:continueUserActivity:restorationHandler 仍然没有被调用。
    • 我刚刚验证它对我有用:github.com/herrernst/NSUserActivityExample 创建一个新的 iOS 单视图 swift Xcode 项目并替换 AppDelegate 和 ViewController。然后,在 Spotlight 中搜索“示例”。
    • 是的,这是正确的答案。您没有在 launchOptions 字典对象中获得 NSUserActivity 对象。您需要在 application:didFinishLaunchingWithOptions: 中返回 YES。当心您是否使用 Facebook SDK 并返回 application:didFinishLaunchingWithOptions: [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions] 它将返回 NO 并且您的 application:continueUserActivity:restorationHandler 代表将不会被调用!
    • 这是处理通用链接时的正确答案。我确定返回 YES/true 的方式是 launchOptions 字典是否为非零。当您手动启动应用程序时,launchOptions 字典为 nil(所以只需在 (BOOL)application:didFinishLaunchingWithOptions: 末尾加上 return launchOptions
    【解决方案2】:

    当来自 NSUserActivity 时,我使用了 UIAlertView 来获取 launchOptions 的描述:

    NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"alert"
                                                        message:[userActivityDictionary description]
                                                       delegate:nil
                                              cancelButtonTitle:@"Okay"
                                              otherButtonTitles:nil];
    [alertView show];
    

    显然,这本字典带有几个我似乎找不到文档的键:

    UIApplicationLaunchOptionsUserActivityIdentifierKey
    UIApplicationLaunchOptionsUserActivityKey
    UIApplicationLaunchOptionsUserActivityTypeKey // there is documentation for this key
    

    似乎 NSUserActivity 对象在此字典中,但从 Apple 的角度来看,尝试访问此对象(例如,可能循环访问字典键并寻找 NSUserActivity 对象)。

    **** 解决方案 ****

    编辑:这里有一些关于如何从 launchOptions 访问 NSUserActivity 对象的实现:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
        if (userActivityDictionary) {
            [userActivityDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                    if ([obj isKindOfClass:[NSUserActivity class]]) {
                        NSLog(@"found NSUserActivity object!");
                    }
                }];
        }
    }
    

    使用此方法,您无需知道未记录的键 UIApplicationLaunchOptionsUserActivityKey 的值。

    如果你对上面的解决方案感到不舒服,另一种方法可能是在你的应用进入该方法时,捕捉 NSUserActivity 对象,

    - (BOOL)application:continueUserActivity:restorationHandler:
    

    然后,将此用户活动设置为 AppDelegate 的属性以供以后检索。

    注意:在测试 Core Spotlight(iOS 9 功能)时,我能够验证是否在冷应用启动时调用了上述方法。

    【讨论】:

    • 是的。我也这样做了。但在那之后你不能访问该对象。即使我将密钥硬编码到 UserActivityKey,也无济于事。
    • 您是如何对密钥进行硬编码的?我们不知道常量 UIApplicationLaunchOptionsUserActivityKey =] 的支持字符串是什么——除非我误解了。您是否尝试过使用 NSDictionary 方法:enumerateKeysAndObjectsUsingBlock 并搜索 object == [NSUserActivity class]
    • 很干净!!是的,枚举是一种干净的方式来解决这个问题,并且由于检查而将是安全的。谢谢@markckim 您可以将其添加到答案中吗?我相信它会帮助别人。
    • 已完成,希望对您有所帮助。我在上面的评论中犯了一个错误,你不能在这里使用==;您应该使用isKindOfClass 进行比较。这反映在主帖的编辑中。
    • @markckim - 从 launchOptions 访问 NSUserActivity 对象是否安全,因为 Apple 没有记录 UIApplicationLaunchOptionsUserActivityKey?您是否知道任何应用程序已在 appstore 中提交,这些应用程序从 launchOptions 访问访问 NSUserActivity 对象?
    【解决方案3】:

    快速回答:

    // Handle universal link
        if let activityDic = launchOptions?[UIApplicationLaunchOptionsUserActivityDictionaryKey] as? [NSObject : AnyObject],
                  activity = activityDic["UIApplicationLaunchOptionsUserActivityKey"] as? NSUserActivity {          
            handleActivity(activity)
        }
    

    【讨论】:

      【解决方案4】:

      里面

      didFinishLaunchingWithOptions

      我只是得到这样的 NSUserActivity:

      目标 C 代码

      if ([launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey])
      {
          NSDictionary *activityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
      
          NSUserActivity *activity = [activityDictionary objectForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
      }
      

      【讨论】:

      • launchOptions 总是为零。如何设置。我想为 UIApplicationLaunchOptionsLocationKey 键做点什么……
      【解决方案5】:
              if
                  let userActivityDictionary = (launchOptions?[UIApplication.LaunchOptionsKey.userActivityDictionary] as? [UIApplication.LaunchOptionsKey: Any]),
                  let userActivity = userActivityDictionary.values.first(where: { $0 is NSUserActivity }) as? NSUserActivity {
      
                  //.....
              }
      

              if
                  let userActivityDictionary = (launchOptions?[UIApplication.LaunchOptionsKey.userActivityDictionary] as? [UIApplication.LaunchOptionsKey: Any]),
                  let userActivity = userActivityDictionary.values.map({ $0 as? NSUserActivity }).compactMap({$0}).first,
                  self.deepLinkHandle(userActivity: userActivity) {
      
                  //.....
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多