#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