2013-02-10 16 views
11

erstellt Hallo, ich eine App schreibe, die mit einem UI-Update und einer internen Statusänderung reagieren sollen, wenn ein lokaler notifcation verwendet wird, um es zu öffnen. Ich bin mit Storyboards und ich habe meine Haupt View-Controller beobachten Statusänderungen einstellen:Anwendung: didFinishLaunchingWithOptions: Brennen Benachrichtigung vor Ziel-Controller

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

In meinem AppDelegate Ich habe diese:

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

Und das funktioniert gut: wenn die App Im Hintergrund läuft der View Controller die Benachrichtigung ab und reagiert entsprechend. (Wenn die App im Vordergrund ausgeführt wird, wird sie ignoriert, da die Benutzeroberfläche direkt verwaltet wird.)

Das Problem tritt auf, wenn die App beendet wurde und die Benachrichtigung empfangen wurde. Ich habe diese Methode in der didFinishLaunchingWithOptions geschrieben, das Telefon vibrieren als schnelle Debug-Technik machen :), und ich tun die Meldung erhalten:

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

Das Telefon vibriert, so dass die Benachrichtigung ist da, aber es doesn scheinen den Beobachter nicht auszulösen. Ich nehme an, dass dies daran liegt, dass die Methode didViewLoad des View-Controllers noch nicht aufgerufen wurde. Ich bin mir nicht sicher, wie ich das schaffen soll. Ich denke, ich könnte UIStoryboards instantiateViewControllerWithIdentifier: Methode verwenden, um sicherzustellen, dass der View-Controller tatsächlich vorhanden ist, aber würde ich keine "extra" -Instanz davon erhalten, zusätzlich zu der, die schließlich vom eigenen Lebenszyklus des Storyboards instanziiert wird ? Nach dem zu urteilen, was die Klassenreferenz-Dokumentation sagt, ist es nicht genau so gemeint.

Fehle ich etwas sehr offensichtlich hier? In der Tat ist mein Ansatz der richtige für diese Art von Situation?

Danke!

Antwort

11

Der View-Controller lädt seine Ansicht nicht, bis etwas nach seiner Ansicht gefragt wird. Zum Startzeitpunkt geschieht das normalerweise nach application:didFinishLaunchingWithOptions: zurück.

Sie fragen sich vielleicht warum. Die Antwort besteht darin, dass Sie zum Startzeitpunkt mehrere View-Controller instanziieren können, von denen einige ausgeblendet sind. Wenn der Root-View-Controller Ihres Fensters beispielsweise eine UINavigationController ist, laden Sie möglicherweise den Navigationscontroller mit einem Stapel von View-Controllern (der Stapel, den der Benutzer beim letzten Ausführen der App gedrückt hatte). Nur der Top-View-Controller dieses Stapels ist sichtbar, so dass die Ansichten der anderen View-Controller nicht geladen werden müssen. Das System wartet, bis application:didFinishLaunchingWithOptions: zurückkehrt, bevor irgendwelche Ansichten geladen werden, so dass nur die erforderlichen Ansichten geladen werden.

Eine Möglichkeit, um Ihr Problem zu umgehen, wäre einfach, den View-Controller nach seiner Ansicht zu fragen und sie so zum Laden zu zwingen. Wenn Ihr View-Controller ist das Fenster Root-View-Controller ist, kann man es auf diese Weise tun:

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

Eine andere Abhilfe wäre, starten Sie die Meldung in der Ansicht Controller initWithCoder: Methode Beobachtung:

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

Diese wird aufgerufen, wenn der View-Controller aus dem MainStoryboard instanziiert wird, was vor der application:didFinishLaunchingWithOptions:-Nachricht geschieht.

+0

Vielen Dank, mit 'initWithcoder:' arbeitete wie ein Charme. Alle diese Schritte im Lebenszyklus eines Objekts können ziemlich verwirrend sein. :) – Jollino

+0

Danke, das funktioniert auch, wenn Sie Push-Benachrichtigungen anstelle von lokalen Benachrichtigungen und kein Storyboard verwenden. Verwenden Sie einfach die 'init'-Methoden. – 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 :) –