应用程序关闭时未处理深度链接React Native iOS应用程序

时间:2019-03-27 19:12:49

标签: ios objective-c react-native deep-linking

我正在为iOS开发React Native应用。

此应用必须能够打开深层链接,并且在后台打开该应用时可以正常工作。 关闭应用程序后,本机iOS代码(Objective-C)无法获取打开应用程序所用的URL。

据我了解它是如何工作的,我必须检查launchOptions的NSDictionary,以查看该应用程序是否已通过URL启动。如果存在与URL初始化相对应的密钥,则我返回true以执行以下代码

- (BOOL)application:(UIApplication *)application
        openURL:(NSURL *)url
        options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  return [RCTLinkingManager application:application openURL:url options:options];

  return YES;
}

必须执行此函数才能获取已打开应用程序的初始Url。这是我的应用程序didFinishWithLaunchOptions的代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary  *)launchOptions
{
    if ([launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]) {
    return true;
  }
}

2 个答案:

答案 0 :(得分:1)

虽然肯定不是一个答案,但我已经(通过可怕的方法)通过更改(或者如果您还没有的话,请添加)来解决此问题(至少直到找到规范的解决方案为止) - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {中的AppDelegate.m到:

- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
  NSURL *url = [userActivity webpageURL];
  BOOL result = [RCTLinkingManager application:application
                          continueUserActivity:userActivity
                            restorationHandler:restorationHandler];
  if([userActivity webpageURL]){
    #if DEBUG
    float seconds = 3.5;
    #else
    float seconds = 1.5;
    #endif
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(seconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      NSURL *newUrl = [NSURL URLWithString:[NSString stringWithFormat:@"MYAPPSCHEME:/%@", url.path]];
      [[UIApplication sharedApplication] openURL:newUrl options:@{} completionHandler:nil];
    });
  }
  
  return result;
}

它基本上检查是否有导致启动的URL,并在“问题解决”之后调用对应用程序的打开URL调用(因为在调试模式下,加载需要更长的时间,我已更改为3.5秒处理得很好)。相应地更改seconds,当然还要更改MYAPPSCHEME。是的,在MYAPPSCHEME:后有一个单斜杠(/),而不是两倍,因为url.path似乎已经有一个斜杠。用我的应用方案替换http[s]的原因是由于某种原因,如果我离开http[s]://,它会启动Safari而不是处理深层链接(在应用为已经运行并已处理网址)。我的应用程序使用常规http链接处理自定义方案的方式相同,因此效果很好,但是请确保对其进行相应设置以使其正常工作。

进行上述更改并重新编译后(不要忘记您在Objective-C部分,而不是JS / React Native),它可以正常工作。我希望看到一个实际的解决方案,而不是棘手的解决方法,但是在此之前,这对我来说已经解决了。

答案 1 :(得分:0)

对讲机不为我处理深层链接的核心问题是,react-native-intercom不会通过didFinishLaunchingWithOptions将初始URL传递给应用程序,如果它是从后台打开的。

相反,react-native-intercom在应用程序启动后立即调用openURL方法,并且应用程序的react-native部分错过了此事件。

解决方案是在openURL方法中创建一个新线程。锁定它以停止执行,然后在React应用程序向本机代码发出信号,表明它已准备好处理深层链接时,将其解锁。该修复程序有些复杂,因此我创建了一个单独的存储库,描述了问题和解决方案。

核心思想可以用代码描述为:

dispatch_queue_t queue = dispatch_queue_create("<yourAppName>.openUrlQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
  while (!DeepLink.canHandleDeepLinks) {
    [DeepLink.canHandleDeepLinksLock wait];
  }
  [DeepLink.canHandleDeepLinksLock unlock];


  dispatch_async(dispatch_get_main_queue(), ^{
    // This method call will trigger the Linking event with URL to be dispatched to your 'javascript' code
    [RCTLinkingManager application:application openURL:url options:options];
  });
});

我已经创建了repository来解决此问题。去,看看吧。