使用URL启动应用程序,但OpenUrl未调用

时间:2015-10-09 09:33:24

标签: ios objective-c url-scheme

我已经实现了一个URL Scheme并使用它通过调用方法将数据传递给我的app。整个代码如下所示

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
    // Check the calling application Bundle ID
    if ([[url scheme] isEqualToString:@"yuvitime"])
    {
        NSLog(@"URL scheme:%@", [url scheme]);
        NSString * yuvitimeRequestValue = [url query];
        NSDictionary * userInfor = [[NSDictionary alloc]initWithObjectsAndKeys:yuvitimeRequestValue, @"YuvitimeRequest", nil];
        NSNotificationCenter * notificationCentre = [NSNotificationCenter defaultCenter];
        [notificationCentre postNotificationName:@"URLSCHEMEACTIVATEDNOTIFICATION" object:self userInfo:userInfor];

        return YES;
    }
    else
        return NO;
}

如果我的应用程序在后台,一切正常。单击URL时,应用程序将返回到Foreground,URL将按照上述函数中的编码进行处理。

但是,如果应用程序已终止(应用程序尚未启动),则通过单击URL,它仅启动应用程序而不调用上面显示的处理函数。

搜索完毕后,我得到的最佳结果是

应用:WillFinishLaunchingWithOptions: 当要求打开URL时,此方法的返回结果与application:didFinishLaunchingWithOptions:方法的返回结果相结合,以确定是否应处理URL。如果任一方法返回NO,则系统不会调用application:openURL:options:方法。如果未实现其中一个方法,则仅考虑实现方法的返回值。

- 应用程序:didFinishLaunchingWithOptions: 此方法表示您处理launchOptions字典中任何键的最后机会。如果您未在application:willFinishLaunchingWithOptions:方法中评估密钥,则应在此方法中查看它们并提供适当的响应。 不是app委托的对象可以通过观察名为UIApplicationDidFinishLaunchingNotification的通知并访问通知的userInfo字典来访问相同的launchOptions字典值。该方法返回后不久发送该通知。 此方法的返回结果与application:willFinishLaunchingWithOptions:方法的返回结果相结合,以确定是否应处理URL。如果任一方法返回NO,则不处理URL。如果未实现其中一个方法,则仅考虑实现方法的返回值。

尽管有这样的解释,我仍然不知道该怎么做,我在网上找不到具体的东西。

由于

此致

8 个答案:

答案 0 :(得分:28)

我同意Kaloyan的说法,“handleOpenURL”从未在应用程序启动时调用。因此,您必须在didFinishLaunchingWithOptions中的“launchOptions”中检查URL。

无论其

我为QuickActions(3D Touch)采用了与Apple example code相同的解决方案。我将URL保存在变量中,然后在applicationDidBecomeActive:处理它。

@interface MyAppDelegate ()
@property (nonatomic, strong) NSURL *launchedURL;
@end

@implementation MyAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.launchedURL = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
    ...
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if (self.launchedURL) {
        [self openLink:self.launchedURL];
        self.launchedURL = nil;
    }
}

- (BOOL)  application:(UIApplication *)application
          openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
       annotation:(id)annotation
{
    NSURL *openUrl = url;

    if (!openUrl)
    {
        return NO;
    }
    return [self openLink:openUrl];
}

- (BOOL)openLink:(NSURL *)urlLink
{
    ...
}

@end

答案 1 :(得分:7)

如果之前没有启动应用程序,则永远不会调用方法“handleOpenURL”。您必须在didFinishLaunchingWithOptions中检查具有键“UIApplicationLaunchOptionsURLKey”的对象的“launchOptions”

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
//call function to handle the url like in handleURL, but do not call handleURL directly

}

答案 2 :(得分:7)

我相信现在有一个更好的答案,

  • application:handleOpenURL:
  • application:openURL:sourceApplication:annotation: 两者都在ios 9中被弃用.Apple的建议是:
  

改为使用application:openURL:options:

application:openURL:options:的行为与旧行为不同,因为它会在应用处于后台或将启动的情况下执行。

因此,您需要处理其中的网址。如下所示:

- (BOOL)application:(UIApplication *)app
        openURL:(NSURL *)url
        options:(NSDictionary<NSString *,id> *)options {

    // Check the calling application Bundle ID
    if ([[url scheme] isEqualToString:@"yuvitime"])
    {
        NSLog(@"URL scheme:%@", [url scheme]);
        NSString * yuvitimeRequestValue = [url query];
        NSDictionary * userInfor = [[NSDictionary alloc]initWithObjectsAndKeys:yuvitimeRequestValue, @"YuvitimeRequest", nil];
        NSNotificationCenter * notificationCentre = [NSNotificationCenter defaultCenter];
        [notificationCentre postNotificationName:@"URLSCHEMEACTIVATEDNOTIFICATION" object:self userInfo:userInfor];

        return YES;
    }
    else
        return NO;
}

答案 3 :(得分:7)

在iOS 13上,我遇到了与该应用程序相同的问题。即使正确实现了- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options方法,它也从未被调用过。

从iOS13开始,将调用SceneDelegates而不是AppDelegate方法。实施

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts

在场景委托中,如果应用程序已经在内存中,它将起作用。但是,为了冷启动,我必须实现回调

-(void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions

也是。
实施

-(void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions

请记住处理未从URL启动应用程序的情况。

以下是有用的参考:https://forums.developer.apple.com/thread/124132

答案 4 :(得分:5)

对于iOS 10,请使用

func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool

答案 5 :(得分:5)

在后台运行应用程序时未调用application(_:open:options:)时,我遇到了同样的问题。造成这种情况的原因是Firebase SDK使用了swizzling方法。

我通过在FirebaseAppDelegateProxyEnabled = NO中设置Info.plist来解决了这个问题

有关其工作原理和影响的详细信息,请点击此处https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in

答案 6 :(得分:0)

对我来说,不要将application(_:open options:)置于外部 AppDelegate {}范围内

答案 7 :(得分:-1)

Swift 2.x

@IBAction func Start(_ sender: AnyObject) {
    timer2.invalidate()
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true)
}




@IBAction func pauseTimer(_ sender: AnyObject) {

    timer.invalidate()

    timer2 = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: Selector(("increaseTimer")), userInfo: nil, repeats: true)



}