【问题标题】:Lauching App with URL (via UIApplicationDelegate's handleOpenURL) working under iOS 4, but not under iOS 3.2在 iOS 4 下使用 URL(通过 UIApplicationDelegate handleOpenURL)启动应用程序,但在 iOS 3.2 下不可用
【发布时间】:2010-08-31 19:24:26
【问题描述】:

我已经实现了 UIApplicationDelegate 的

application:didFinishLaunchingWithOptions:

application:handleOpenURL:

根据规范,即

application:didFinishLaunchingWithOptions:
returns YES 

application:handleOpenURL: opens the URL. 

代码在 iOS 4 下工作(在这两种情况下,即应用程序启动时和从挂起状态变为活动时)。但是,该代码在 iOS 3.2 下无法运行。

【问题讨论】:

  • 3.2有什么问题?错误信息?它中断的代码行?
  • 如果委托回答了消息 didFinishLaunchingWithOptions,似乎根本没有收到消息 handleOpenURL,即使该方法返回 YES。 API 文档向我提出了不同的行为。

标签: iphone ipad ios iphone-sdk-3.2


【解决方案1】:

我会回答我自己的问题。找到解决方案花了我一段时间,非常令人沮丧。如果您进行互联网搜索,您会找到一些部分答案,但我仍然花了一些时间来制定以下解决方案,我希望它能增加一些清晰度。

首先,您的应用的推荐行为如下所示(请参阅 iOS Ref Lib 中的 Opening Supported File Types):

  • 不要实现applicationDidFinishLaunching:(请参阅UIApplicationDelegate 的注释)。
  • 实现application:didFinishLaunchingWithOptions:并检查URL,如果可以打开返回YES,否则返回NO,但不要打开。
  • 实现application:handleOpenURL:并打开URL,成功返回YES,否则返回NO。

在 iOS 4 中,将 URL 传递给应用会导致以下两种行为之一:

  • 如果应用程序启动,则调用application:didFinishLaunchingWithOptions:,如果application:didFinishLaunchingWithOptions:返回YES,则调用application:handleOpenURL:
  • 如果应用从挂起状态变为活动状态,则不会调用 application:didFinishLaunchingWithOptions:,但会调用 application:handleOpenURL:

但是,在 iOS 3.2 中,似乎从未调用过 application:handleOpenURL:!可以在Handling URL Requests 中找到有关 iOS 3.2 下行为不同的提示。在那里你会发现application:handleOpenURL: 被调用,如果application:didFinishLaunchingWithOptions: 没有实现,但是applicationDidFinishLaunching: 被实现了。但是如果实现了application:didFinishLaunchingWithOptions:,则不会调用application:handleOpenURL:

因此,使代码在 3.2 和 4.0 下工作的一种解决方案是:

  • 打开application:didFinishLaunchingWithOptions:中的URL,然后返回NO以防止调用application:handleOpenURL:
  • 打开application:handleOpenURL:中的URL,以防您低于4.0并且应用处于暂停状态。

我在另一篇文章中找到了这个解决方案,但我很困惑,因为它与 iOS Ref Lib 文档中的建议相矛盾(即我们应该在 application:didFinishLaunchingWithOptions: 中返回 YES)。 (那时我没有意识到文档与它本身相矛盾)。

我相信现在的 iOS 4.0 行为会是未来的行为我更喜欢下面的解决方案:

  • 不要实现applicationDidFinishLaunching:
  • 执行application:didFinishLaunchingWithOptions:并检查URL,如果可以打开则返回YES,否则返回NO,但不要打开它。如果我们使用的是 3.2,请打开 URL。
  • 实现application:handleOpenURL:并打开URL,成功返回YES,否则返回NO。

所以总而言之,我实现了 iOS 4 的行为并将以下行添加到 application:didFinishLaunchingWithOptions:

    if([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3.2"]) {
        [self application:application handleOpenURL:url];
    }

这使得代码在 3.2 下工作。

【讨论】:

  • 谢谢,我遇到了同样的问题,这个答案为我节省了很多时间。
  • 直到我意识到我的项目使用 3.2 的 Base SDK 编译但在 4.0 模拟器上运行之前,我仍然无法让它工作。结果?当变为活动状态时,将调用上述方法中的任何一个。一旦我将基础 SDK 切换到 4.0,一切正常。不知道如何让它在 3.2 ipad tho 中工作。
  • 好点。另外:模拟器对我来说不是一个非常可靠的测试环境。我发现可以在模拟器上工作的东西不在设备上,反之亦然。一个例子:stackoverflow.com/questions/3616981 - 但模拟器现在已经改进了。
  • 我会在 if 语句中添加 url&&
  • 这种行为是否也出现在 iOS 3.2.2(3.2 iOS 类别中的最新版本)中?如果是,那么我们可以检查 iOS 是否低于 4.0(以保持兼容旧 iPod 和 iPhone)
【解决方案2】:

application:handleOpenURL: 现已弃用。

从 iOS 4.2 开始,您可以使用它来打开 URL:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 
        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

文档:

https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html

【讨论】:

    【解决方案3】:

    我开始编写使用 Dropbox api 的应用程序。为了理解概念,我使用我在 dropbox/developer documentation 中提到的密钥/秘密运行了一个示例应用程序。 示例应用程序开始工作后,我为我的应用程序使用了相同的密钥/秘密值。

    对于示例应用程序,handleOpenURL(或 iOS 4.2 上的 openURL)的实现按预期执行。出于某种奇怪的原因,我的应用程序并非如此。我的应用程序进入后台以显示 Dropbox 的登录屏幕和身份验证页面。成功登录和身份验证后,我的应用程序从未进入前台。平台模拟器和设备 (iPad) 都是如此

    我几乎尝试了互联网上列出的所有内容,包括这篇文章。谢谢。但是没有成功。

    最后,当我执行以下操作时,它开始为我的应用程序工作:

    • 在模拟器上,选择“iOS 模拟器 --> 重置内容和设置”,然后重置。
    • 在设备上,我删除了与示例应用程序相关的可执行文件,然后删除了与其关联的缓存。

    【讨论】:

      【解决方案4】:

      application:DidFinishLaunchingWithOptions末尾添加以下内容:

      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      
          ...    
      
          NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
          if (url != nil && [url isFileURL]) {
              return YES;
          }  else return NO;
      } // End of application:didFinishLaunchingWithOptions:
      
      // New method starts 
      -(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
      {
          mvc = [nc.viewControllers objectAtIndex:0];
          if (url != nil && [url isFileURL]) {
              [mvc handleOpenURL:url];
          }
          return YES;
      }
      

      mvc 是我的主要 ViewController,而 nc 是我的导航控制器。

      然后在 MainViewController 中,执行如下操作:

      - (void)handleOpenURL:(NSURL *)url {
          [self.navigationController popToRootViewControllerAnimated:YES];
      
          // Next bit not relevant just left in as part of the example
          NSData *jsonData = [NSData dataWithContentsOfURL:url];        
          NSError *error;
          NSDictionary *dictionary = [[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error] objectAtIndex:0];
          [self managedObjectFromStructure:dictionary withManagedObjectContext:self.context];
          ...
      }
      

      当然是在.h 中声明handleOpenURL 之后。

      感谢克里斯蒂安为此付出的努力。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-13
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多