使用URL启动应用程序(通过UIApplicationDelegate handleOpenURL)在iOS 4下运行,但不在iOS 3.2下运行

时间:2010-08-31 19:24:26

标签: iphone ipad ios iphone-sdk-3.2

我已经实现了UIApplicationDelegate的

application:didFinishLaunchingWithOptions:

application:handleOpenURL:

根据规范,即

application:didFinishLaunchingWithOptions:
returns YES 

application:handleOpenURL: opens the URL. 

代码在iOS 4下运行(在两种情况下,即应用程序启动时以及从暂停状态变为活动状态时)。但是,该代码在iOS 3.2下无效。

4 个答案:

答案 0 :(得分:33)

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

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

  • 请勿实施applicationDidFinishLaunching:(请参阅UIApplicationDelegate上的说明)。
  • 实施application:didFinishLaunchingWithOptions:并检查网址,如果可以打开则返回YES,否则返回NO,但不要打开它。
  • 实施application:handleOpenURL:并打开网址,如果成功则返回YES,否则返回NO。

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

  • 如果该应用已启动,则会调用application:didFinishLaunchingWithOptions:并在application:handleOpenURL:返回YES时调用application:didFinishLaunchingWithOptions:
  • 如果应用从暂停状态变为活动状态,则不会调用application:didFinishLaunchingWithOptions:,但会调用application:handleOpenURL:

然而,在iOS 3.2中,似乎永远不会调用application:handleOpenURL:!可以在Handling URL Requests中找到iOS 3.2下行为不同的提示。如果application:handleOpenURL:未实现,则会发现application:didFinishLaunchingWithOptions:被调用,但applicationDidFinishLaunching:已实现。但是,如果application:handleOpenURL:已实施,则不会调用application:didFinishLaunchingWithOptions:

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

  • application:didFinishLaunchingWithOptions:中打开网址,但返回“否”以阻止调用application:handleOpenURL:
  • 如果您的版本低于4.0且应用处于暂停状态,请在application:handleOpenURL:中打开该网址。

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

我相信当前的iOS 4.0行为将是未来的行为我更喜欢以下解决方案:

  • 不要实施applicationDidFinishLaunching:
  • 实施application:didFinishLaunchingWithOptions:并检查网址,如果可以打开则返回YES,否则返回NO,但不要打开它。如果我们在3.2上,请打开URL。
  • 实施application:handleOpenURL:并打开网址,如果成功则返回YES,否则返回NO。

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

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

使代码在3.2下工作。

答案 1 :(得分:7)

application:handleOpenURL:现已弃用。

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

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

答案 2 :(得分:2)

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

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

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

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

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

答案 3 :(得分:0)

将以下内容添加到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之后。

感谢Christian为此付出的努力。