Подтвердить что ты не робот

Application: didFinishLaunchingWithOptions: создается уведомление об увольнении перед контроллером назначения

Здравствуйте, Я пишу приложение, которое должно отвечать обновлением пользовательского интерфейса и внутренним изменением статуса, когда для его открытия используется локальное нотификация. Я использую раскадровки, и я установил свой главный контроллер просмотра для наблюдения за изменениями состояния:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // ...
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeByNotification:) name:@"Resume" object:nil];
}

В моем делете приложения у меня есть следующее:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    if (application.applicationState == UIApplicationStateInactive)
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:notification.userInfo];
    }
}

И это отлично работает: если приложение работает в фоновом режиме, контроллер просмотра перехватит уведомление и соответствующим образом отреагирует. (Если приложение работает на переднем плане, оно игнорируется, потому что пользовательский интерфейс позаботится напрямую.)

Проблема возникает, когда приложение было убито и получено уведомление. Я написал это в методе didFinishLaunchingWithOptions, заставляя телефон вибрировать как быструю технику отладки:), и я получаю уведомление:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotification)
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:localNotification.userInfo];
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    }

    return YES;
}

Телефон вибрирует, поэтому уведомление есть, но он, похоже, не вызывает наблюдателя. Я полагаю, что это связано с тем, что еще не был вызван метод didViewLoad контроллера. Я не знаю, как это сделать. Я полагаю, что я мог бы использовать UIStoryboard instantiateViewControllerWithIdentifier: метод, чтобы убедиться, что диспетчер представлений на самом деле существует, но не могу ли я получить "лишний" экземпляр этого объекта, в дополнение к тому, который в конечном итоге будет создан на основе собственного жизненного цикла раскадровки? Судя по тому, что говорится в справочной документации по классу, оно не предназначено для такого рода вещей.

Я пропустил что-то очень очевидное здесь? На самом деле, мой подход правильный для такого рода ситуации?

Спасибо!

4b9b3361

Ответ 1

Контроллер представления не загружает свой вид, пока что-то не спросит его о своем представлении. Во время запуска это обычно происходит после возврата application:didFinishLaunchingWithOptions:.

Вы можете удивиться, почему. Ответ заключается в том, что вы можете создавать несколько контроллеров представления во время запуска, некоторые из которых скрыты. Например, если ваш контроллер корневого окна Windows является UINavigationController, вы можете загрузить контроллер навигации с помощью стека контроллеров представлений (стек, который пользователь нажал в последний раз, когда приложение запустилось). Отображается только контроллер верхнего уровня этого стека, поэтому нет необходимости загружать представления других контроллеров представлений. Система ждет, пока application:didFinishLaunchingWithOptions: не вернется, прежде чем загружать какие-либо представления, чтобы загружать только необходимые представления.

Таким образом, одним из способов обойти вашу проблему было бы просто спросить контроллер вида для его представления, заставив его загрузить. Если ваш контроллер просмотра является контроллером корневого окна, вы можете сделать это следующим образом:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotification) {
        [[self.window rootViewController] view];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"Resume" object:self userInfo:localNotification.userInfo];
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    }

    return YES;
}

Другим обходным решением было бы начать наблюдение за уведомлением в вашем методе контроллера initWithCoder::

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeByNotification:) name:@"Resume" object:nil];
    }
    return self;
}

Это вызывается, когда контроллер представления создается из MainStoryboard, который происходит до сообщения application:didFinishLaunchingWithOptions:.