2013-02-10 1 views
11

Здравствуйте, Я пишу приложение, которое должно отвечать с обновлением пользовательского интерфейса и внутренним изменением состояния, когда местный notifcation используется, чтобы открыть его. Я использую раскадровку и я настроил мой главный контроллер представления, чтобы наблюдать изменения состояния:применение: 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 контроллера вида еще не вызван. Я не знаю, как это сделать. Я полагаю, что я мог бы использовать метод instantiateViewControllerWithIdentifier: UIStoryboard, чтобы убедиться, что на самом деле есть контроллер представления, но не могу ли я получить его «лишний» экземпляр, в дополнение к тому, который в конечном итоге будет создан в результате собственного жизненного цикла раскадровки ? Судя по тому, что говорится в справочной документации по классу, это не значит, что это нужно делать.

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

Спасибо!

ответ

11

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

Вы можете удивиться, почему. Ответ заключается в том, что вы можете создавать несколько контроллеров представления во время запуска, некоторые из которых скрыты. Например, если контроллер корневого представления вашего окна - 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:.

+0

Спасибо, используя 'initWithcoder:' работал как шарм. Все эти шаги в жизненном цикле объекта могут запутаться. :) – Jollino

+0

Спасибо, это работает, если вы используете push-уведомления вместо локальных уведомлений и никакой раскадровки. Просто используйте методы 'init'. – yoeriboven

+0

['init (coder:)'] (https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/index.html#//apple_ref/occ/intfm/NSCoding/initWithCoder :) –