2013-02-10 51 views
11

你好, 之前目標控制器我寫的時候本地notifcation來打開它應該與UI更新和內部狀態的變化做出響應的應用內觸發通知。我使用的故事板,我已經建立了我的主視圖控制器來觀察狀態的變化:應用中: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; 
} 

的手機不振動,從而通知是存在的,但它不似乎不會觸發觀察員。我想這是因爲視圖控制器的didLoadLoad方法尚未被調用。我不知道如何解決這個問題。我想我可以使用UIStoryboard的instantiateViewControllerWithIdentifier:方法來確保視圖控制器實際存在,但除了最終將由故事板自己的生命週期實例化之外,我不會得到它的「額外」實例?根據課堂參考文獻所述,這並不完全是爲了做這種事情。

我在這裏錯過了一些非常明顯的東西嗎?事實上,對於這種情況,我的方法是否正確?

謝謝!

回答

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 2013-02-10 20:52:37

+0

謝謝,如果你使用推送通知,而不是本地通知,並沒有故事板,這也適用。只需使用'init'方法即可。 – yoeriboven 2013-10-09 14:00:41

+0

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

相關問題