Запуск приложения iOS из-за NSUserActivity. Как получить доступ к этому объекту?

Итак, тестирование некоторых бета-функций ios9 на данный момент, но класс NSUserActivity был недоступен некоторое время, которое используется при передаче обслуживания.

В основном это он. Когда приложение запускает doe в NSUserActivity, я вижу, что это launchOptions имеет набор ключей.

    NSDictionary *userActivityKey = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

В принципе метод никогда не вызывается.

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler

Это имеет смысл, поскольку приложение просто открывается из-за активности. Но меня это озадачивает.

Когда я проверяю launchOptions, я не могу получить доступ к NSUserActivity. По-видимому, ОС создает для вас этот объект??

Разве кто-нибудь из вас с этим справился?

Ответы

Ответ 1

Я использовал UIAlertView, чтобы получить описание launchOptions при выходе из NSUserActivity:

NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"alert"
                                                    message:[userActivityDictionary description]
                                                   delegate:nil
                                          cancelButtonTitle:@"Okay"
                                          otherButtonTitles:nil];
[alertView show];

По-видимому, этот словарь содержит пару ключей, которые, как мне кажется, не могут найти документацию для:

UIApplicationLaunchOptionsUserActivityIdentifierKey
UIApplicationLaunchOptionsUserActivityKey
UIApplicationLaunchOptionsUserActivityTypeKey // there is documentation for this key

введите описание изображения здесь

Кажется, что объект NSUserActivity находится внутри этого словаря, но он может быть не очень хорош с точки зрения Apple (или он может сломаться, если Apple решит изменить ситуацию), чтобы попытаться получить доступ к этому объекту (например, возможно, перейдя через словарные ключи и поиск объекта NSUserActivity).

**** Решение ****

EDIT: Здесь представлена ​​некоторая реализация того, как получить доступ к объекту NSUserActivity из launchOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSDictionary *userActivityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
    if (userActivityDictionary) {
        [userActivityDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                if ([obj isKindOfClass:[NSUserActivity class]]) {
                    NSLog(@"found NSUserActivity object!");
                }
            }];
    }
}

Используя этот метод, вам не нужно знать значение недокументированного ключа, UIApplicationLaunchOptionsUserActivityKey.

Если вам неудобно решение выше, другим методом может быть захват объекта NSUserActivity, когда ваше приложение входит в этот метод,

- (BOOL)application:continueUserActivity:restorationHandler:

Затем установите эту активность пользователя как свойство вашего AppDelegate для последующего поиска.

Примечание. Я смог проверить, что вышеописанный метод вызывается при запуске холодного приложения при тестировании Core Spotlight (функция iOS 9).

Ответ 2

Вы не должны делать этого. Вы должны вернуть YES из -(BOOL)application:didFinishLaunchingWithOptions:, затем будет вызываться -(BOOL)application:continueUserActivity:restorationHandler. Apple docs скажет:

НЕТ, если приложение не может обработать ресурс URL или продолжить работу с пользователем, иначе верните YES.

Ответ 3

Быстрый ответ:

// Handle universal link
    if let activityDic = launchOptions?[UIApplicationLaunchOptionsUserActivityDictionaryKey] as? [NSObject : AnyObject],
              activity = activityDic["UIApplicationLaunchOptionsUserActivityKey"] as? NSUserActivity {          
        handleActivity(activity)
    }

Ответ 4

Внутри

didFinishLaunchingWithOptions

Я просто получаю NSUserActivity следующим образом:

Objective C code

if ([launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey])
{
    NSDictionary *activityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

    NSUserActivity *activity = [activityDictionary objectForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
}

Ответ 5

        if
            let userActivityDictionary = (launchOptions?[UIApplication.LaunchOptionsKey.userActivityDictionary] as? [UIApplication.LaunchOptionsKey: Any]),
            let userActivity = userActivityDictionary.values.first(where: { $0 is NSUserActivity }) as? NSUserActivity {

            //.....
        }

или же

        if
            let userActivityDictionary = (launchOptions?[UIApplication.LaunchOptionsKey.userActivityDictionary] as? [UIApplication.LaunchOptionsKey: Any]),
            let userActivity = userActivityDictionary.values.map({ $0 as? NSUserActivity }).compactMap({$0}).first,
            self.deepLinkHandle(userActivity: userActivity) {

            //.....
        }