2013-07-18 38 views
9

我想在我的應用程序中不使用故事板進行狀態恢復。我看到我的主應用程序ViewController在狀態恢復期間實例化了兩次 - 您如何確保它只創建一次?在狀態恢復期間創建和恢復UIViewControllers的正確方法?

我理解流程的方式application:willFinishLaunchingWithOptionspplication:didFinishLaunchingWithOptions將使用commonInit方法來設置應用程序UIWindow及其rootViewController。在我的情況下,rootViewController是一個名爲'MyMainViewController'的UINavigationController,用作UINavigation的rootViewController。

沿邊這個我也處理分別willEncodeRestorableStateWithCoderdidDecodeRestorableStateWithCoder。但是,當我到達我的didDecodeRestorableStateWithCoder時,我看到創建了兩個單獨的MyMainViewController實例。

確保在還原期間只創建一個UIViewController的方法是什麼?

  • 創建新實例MyMainViewController(#1),通過應用:willFinishLaunchingWithOptions:
  • MyMainViewController的viewControllerWithRestorationIdentifierPath:恢復過程中的呼叫

    順序編碼調用和 MainViewController恢復(#2)

  • 應用:didDecodeRestorableStateWithCoder:被調用並且UINavigationController被解碼並分配給self.window

這是我在我的AppDelegate正在做:

NSString * const kRootViewControllerKey = @"RootViewControllerKey"; 

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    [self commonInitWithOptions:launchOptions]; 
    return YES; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    [self commonInitWithOptions:launchOptions]; 
    return YES; 
} 

- (void)commonInitWithOptions:(NSDictionary *)launchOptions { 

    static dispatch_once_t predicate; 
    dispatch_once(&predicate,^{ 

     // While this will be called only once during the lifetype of the app, when the process is killed 
     // and restarted, I wind up with an instance of MyMainViewController created first from here 
     // and then once again, during MyMainViewController's viewControllerWithRestorationIdentifierPath:coder 
     // that's invoked later on. 

     UIViewController *rootViewController = [MyMainViewController alloc] init]; 
     UINavigationController *aNavController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; 

     aNavController.navigationBarHidden = YES; 
     aNavController.restorationIdentifier = NSStringFromClass([aNavController class]); 

     UIWindow *aWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
     aWindow.rootViewController = aNavController; 
     aWindow.restorationIdentifier = NSStringFromClass([window class]); 

     self.window = aWindow; 
    }); 
} 

// Encode app delegate level state restoration data 
- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder { 
    [coder encodeObject:self.window.rootViewController forKey:kRootViewControllerKey]; 
} 

// Decode app delegate level state restoration data 
- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder { 

    // Find the preserved root view controller and restore with it 
    UINavigationController *navControlller = [coder decodeObjectForKey:kRootViewControllerKey]; 

    if (navControlller) { 
     self.window.rootViewController = navControlller; 
    } 

} 
+0

你有沒有找到解決這個問題?我遇到了完全相同的問題,看到我的視圖控制器被初始化了兩次。 – djibouti33

+0

不 - 從來沒有。我不知道如何解決這個問題,因爲我無法使用故事板。 –

回答

0

這裏只有永遠應該是我的根視圖類的一個實例,所以我解決它通過添加類方法alloc和初始化類只有一次否則返回值:

+ (id) initOnce { 
    static id view_ref; 

    if(!view_ref) 
     view_ref = [[UIViewController alloc] init]; 

    return view_ref; 
} 

現在,當類通過[UIViewController中initOnce]初始化中,相同的參考視圖總是獲取返回,在willFinishLaunchingWithOptions或viewControllerWithRestorationIdentifierPath是否。

+0

此外,您可以不在根視圖上設置.restorationClass,並且UIKit狀態恢復似乎執行「正確的事情」。 – jasonjwwilliams