Глубокая ссылка не обрабатывается при закрытии приложения React Native iOS app

#ios #objective-c #react-native #deep-linking

#iOS #objective-c #react-native #глубокая ссылка

Вопрос:

Я разрабатываю приложение React Native для iOS.

Это приложение должно иметь возможность открывать глубокие ссылки, и оно отлично работает, когда приложение открыто в фоновом режиме. При закрытии приложения собственный код iOS (Objective-C) не получает URL, с помощью которого было открыто приложение.

Поскольку я понимаю, как это работает, я должен проверить NSDictionary в launchOptions, чтобы узнать, было ли запущено приложение через 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;
  }
}
  

Комментарии:

1. Смогли ли вы решить это или нет, поскольку мы также застряли в том же положении только в IOS, пожалуйста, дайте мне знать, если вы найдете решение? Спасибо

Ответ №1:

Основная проблема Intercom, не обрабатывающая глубокие ссылки для меня, заключалась в том, что react-native-intercom не передает исходный URL приложению через didFinishLaunchingWithOptions , если оно открыто в фоновом режиме.

Вместо этого react-native-intercom вызывает openURL метод сразу после запуска приложения, и react-native часть приложения пропускает это событие.

Решением для этого было создать новый поток в openURL методе. Заблокируйте его, чтобы остановить выполнение, а затем разблокируйте tread, когда приложение 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];
  });
});
  

Я создал репозиторий с решением этой проблемы. Иди, проверь это.

Ответ №2:

Хотя это определенно не ответ, я (ужасно) обошел эту проблему (по крайней мере, до тех пор, пока не будет доступно каноническое решение), изменив (или, если у вас еще нет, добавив) - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { in 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 resu<
}
  

В основном он проверяет, доступен ли URL-адрес, который вызвал запуск, и вызывает вызов open URL для приложения после того, как «все устаканилось» (поскольку в режиме отладки загрузка занимает больше времени, я изменил на 3,5 секунды, что отлично справляется с этим). Измените seconds и, конечно MYAPPSCHEME , соответствующим образом. И ДА, после есть MYAPPSCHEME: одиночная косая черта (/), а не двойная, поскольку url.path , похоже, у нее уже есть косая черта в начале. Причина замены http[s] на my app scheme заключается в том, что по какой-то причине она запускает Safari вместо обработки глубокой ссылки, если я ухожу http[s]:// (что не имеет место, когда приложение уже запущено и URL обрабатывается). Мое приложение обрабатывает пользовательские схемы таким же образом, как и обычные http-ссылки, поэтому оно работает хорошо, но убедитесь, что вы настроили его соответствующим образом, чтобы оно работало.

После внесения вышеуказанных изменений и перекомпиляции (не забывайте, что вы работаете в части Objective-C, а не JS / React Native) это сработало. Я бы хотел увидеть реальное решение, а не халтурный обходной путь, но до тех пор это исправило это для меня.

Комментарии:

1. хороший обходной путь, у меня это сработало! для будущих читателей MYAPPSCHEME необходимо заменить на схему в XCode -> Targets [ваше приложение] -> Info -> Типы URL-адресов -> Схемы URL