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

27

我已经实现了一个URL Scheme,并使用它通过调用方法将数据传递到我的应用程序中。以下是整个代码:

- (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。
然而,如果应用程序被终止(应用程序尚未启动),则仅会启动应用程序,而不调用上面显示的处理函数。
经过搜索,我找到的最佳结果是:
application:WillFinishLaunchingWithOptions: 当被要求打开URL时,此方法的返回结果与application:didFinishLaunchingWithOptions:方法的返回结果组合起来确定是否应处理URL。如果任一方法返回NO,则系统不会调用application:openURL:options:方法。如果您没有实现其中一个方法,则仅考虑实现方法的返回值。
- application:didFinishLaunchingWithOptions: 此方法代表您处理launchOptions字典中任何键的最后机会。如果您没有在您的application:willFinishLaunchingWithOptions:方法中评估这些键,则应在此方法中查看它们并提供适当的响应。 非应用程序委托的对象可以通过观察名为UIApplicationDidFinishLaunchingNotification的通知并访问通知的userInfo字典来访问相同的launchOptions字典值。该通知在此方法返回后不久发送。 此方法的返回结果与application:willFinishLaunchingWithOptions:方法的返回结果组合起来确定是否应处理URL。如果任一方法返回NO,则不处理URL。如果您没有实现其中一个方法,则仅考虑实现方法的返回值。
尽管有解释,我仍然不知道该如何操作,并且在网上找不到其他具体的信息。
谢谢!
敬礼!

你确定-(BOOL)application:handleOpenURL:没有被调用吗?问题似乎是在应用程序初始化时没有任何对象监听通知。你可以在这里显示一个警告框来再次确认。 - larva
@ABáo 如果我们假设问题出在项目没有监听通知上,我该如何检查和解决它呢?谢谢! - progammingBeignner
  • (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { [[[UIAlertView alloc] initWithTitle:@"处理OpenURL" message:@"" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil] show]; return YES; }
- larva
在上面的代码中,你需要调用UIAlertView而不是alertViewController。尝试一下并再次确认。 - larva
@ABáo,你说得对!!!警报被调用了!哈哈。天啊,谢谢你!顺便问一下,你有什么建议来解决对象没有监听到通知的问题吗?我猜我发布通知的时间太早了?在我的视图控制器准备好接收它之前就发布了,所以当appDelegate发布通知时,我的ViewController根本没有接收到它。 - progammingBeignner
显示剩余4条评论
9个回答

29

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

然而,

我采用了与苹果示例代码相同的解决方案用于快捷操作(3D Touch)。我将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

16

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

从iOS 13开始,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


兄弟,你就是那个人。你的解决方案是唯一有效的。非常感谢你,兄弟。 - Siddhartha Moraes

9
我相信现在有一个更好的答案,因为以下两个方法都已经过时了:
  • application:handleOpenURL:
  • application:openURL:sourceApplication:annotation:
苹果公司建议使用以下方法代替:

使用 application:openURL:options: 代替。

application:openURL:options: 和旧方法有不同的行为,因为它将在应用程序处于后台或即将启动的情况下执行。因此,您只需要在其中处理URL打开,如下所示:
- (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;
}

8
如果应用程序被杀死并且通过URL Scheme打开,则不会调用此方法。我正在iOS模拟器上尝试它,版本是iOS 9.1。 - Desert Rose

8

你好,当应用程序之前没有启动时,“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

}

1
这个答案已经过时了,你应该使用application:openURL:options:,它也可以在冷启动时调用。 - Peter Johnson

6

iOS 10版本,请使用:

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

5
我在应用程序处于后台时,application(_:open:options:) 没有被调用时遇到了同样的问题。这是由于 Firebase SDK 使用了方法混合技术导致的。
我通过在 Info.plist 中将 FirebaseAppDelegateProxyEnabled = NO 来解决这个问题。
如需了解更详细的信息以及它对你的影响,请阅读这里的内容:https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in

0

对我来说,不要在AppDelegate {}作用域之外使用application(_:open options:)方法


0

我发布通知的时间太早了,通过增加延迟来解决了我的问题。

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

  NSString *urlStr = url.absoluteString;
  BOOL ret = [urlStr hasPrefix:@"dxylink://joinCourse"];
  if(ret){
    NSLog(@"url query:%@",[url query]);
    NSArray *paramsArray = [[url query] componentsSeparatedByString:@"&"];
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    for(NSString *param in paramsArray){
      NSArray *curParams = [param componentsSeparatedByString:@"="];
      [params setValue:[curParams lastObject] forKey:[curParams firstObject]];
    }
    NSArray *arr = [NSArray arrayWithArray:params.allValues];
    self.codeStr = arr.firstObject;
    [self performSelector:@selector(postNoti) withObject:nil afterDelay:1];
    NSLog(@"url scheme params:%@",params);
  }
  return YES;
}

- (void)postNoti {
  [[NSNotificationCenter defaultCenter] postNotificationName:@"LinkNoti" object:nil userInfo:@{@"str":self.codeStr}];
}`

-1

Swift 2.x

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {

        if (url.scheme == "yuvitime") {
            print("URL scheme:\(url.scheme)")
            let yuvitimeRequestValue = url.query!
            let userInfor = [
                "YuvitimeRequest" : yuvitimeRequestValue
            ]

            let notificationCentre = NSNotificationCenter.defaultCenter()
            notificationCentre.postNotificationName("URLSCHEMEACTIVATEDNOTIFICATION", object: self, userInfo: userInfor)
            return true
        }
        else {
            return false
        }

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接