2013-02-10 8 views
11

Witaj, Piszę aplikację, która powinna reagować z aktualizacją UI i wewnętrznej zmiany statusu kiedy miejscowy notifcation jest używany, aby go otworzyć. Używam storyboardy i mam skonfigurować mój główny kontroler widoku, aby obserwować zmiany stanu:aplikacji: didFinishLaunchingWithOptions: wypalanie powiadomienie zanim kontroler docelowy jest tworzony

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

w moim app delegata mam to:

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

I to działa dobrze: jeśli aplikacja jest uruchomiony w tle kontroler widoku przechwyci powiadomienie i odpowiednio zareaguje. (Jeśli aplikacja działa na pierwszym planie, zostanie zignorowana, ponieważ interfejs użytkownika jest obsługiwany bezpośrednio.)

Problem pojawia się, gdy aplikacja została zabita, a powiadomienie jest odbierane. Pisałem to w metodzie didFinishLaunchingWithOptions, dzięki czemu wibracje telefonu jako szybki techniki debugowania :) i zrobić otrzymać powiadomienie:

- (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; 
} 

telefon będzie wibrował więc zgłoszenie jest tam, ale to nie robi Zdaje się, że uruchamia obserwatora. Przypuszczam, że dzieje się tak dlatego, że metoda didViewLoad kontrolera widoku nie została jeszcze wywołana. Nie jestem pewien, jak to obrobić. Przypuszczam, że mógłbym użyć metody instantiateViewControllerWithIdentifier: UIStoryboard, aby upewnić się, że kontroler widoku rzeczywiście istnieje, ale nie dostałbym "dodatkowej" instancji, oprócz tego, który ostatecznie zostanie utworzony przez własny cykl życia storyboardu ? Sądząc po tym, co mówi dokumentacja klasowa, nie jest to dokładnie takie, żeby robić tego rodzaju rzeczy.

Czy brakuje tu czegoś bardzo oczywistego? Czy moje podejście jest właściwe dla tego rodzaju sytuacji?

Dzięki!

Odpowiedz

11

Kontroler widoku nie ładuje swojego widoku, dopóki coś nie poprosi o jego widok. W momencie uruchomienia, zwykle dzieje się po zwrocie application:didFinishLaunchingWithOptions:.

Możesz się zastanawiać, dlaczego. Odpowiedź brzmi, że możesz zainicjować kilka kontrolerów widoku w czasie uruchamiania, z których niektóre są ukryte. Na przykład, jeśli kontrolerem widoku głównego okna jest UINavigationController, można załadować kontroler nawigacyjny za pomocą stosu kontrolerów widoku (stosu, który użytkownik pchnął podczas ostatniego uruchomienia aplikacji). Widoczny jest tylko kontroler widoku z góry tego stosu, więc nie ma potrzeby ładowania widoków innych kontrolerów widoku. System czeka aż application:didFinishLaunchingWithOptions: powróci przed załadowaniem jakichkolwiek widoków, aby załadować tylko niezbędne widoki.

Jednym ze sposobów obejścia problemu byłoby po prostu poprosić kontroler widoku o jego widok, co zmusiłoby go do załadowania. Jeśli kontroler widok jest korzeń widok kontroler okna, można zrobić to w ten sposób:

- (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; 
} 

Odmienny Rozwiązaniem byłoby rozpocząć obserwację powiadomienie w widoku kontrolera initWithCoder: metody:

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

This jest wywoływana, gdy kontroler widoku jest tworzony z MainStoryboard, co dzieje się przed komunikatem application:didFinishLaunchingWithOptions:.

+0

Dziękuję, użycie 'initWithcoder:' działało jak czar. Wszystkie te kroki w cyklu życia obiektu mogą stać się dość mylące. :) – Jollino

+0

Dzięki, działa to również w przypadku powiadomień push zamiast powiadomień lokalnych i bez scenorysu. Po prostu użyj metod 'init'. – yoeriboven

+0

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

Powiązane problemy