2012-04-23 81 views
20

我正在構建使用故事板的IOS 5.1 Web客戶端應用程序。我的一個操作是「註銷」,在此期間我想將根視圖重置爲由Storyboard的根視圖創建的初始視圖。 (當您登錄時,某些查看項目會根據您的身份被刪除或添加;當您註銷時,我想將它們重置爲默認值,這在故事板中已指定。)在註銷時重置故事板

我意識到我可以以編程方式重置/重新添加所有元素,但那麼故事板有什麼用處?我認爲必須通過重新加載視圖文件才能回到原點,對吧?

+0

你有沒有想過這個?我也有同樣的需求...... – 2012-09-10 02:44:23

回答

28

我發現以下方法適用於我。請注意,我使用ARC,但不確定這是否與解決方案有很大關係。

_initalStoryboard = self.window.rootViewController.storyboard; 

(顯然有可變的實例UIStoryboard* _initalStoryboard;)我有以下函數定義

然後:首先,在應用程序委託類,在application:didFinishLaunchingWithOptions:我與下面的代碼行捕獲inital故事板實例在我的應用程序委託:

- (void)resetWindowToInitialView 
{ 
    for (UIView* view in self.window.subviews) 
    { 
     [view removeFromSuperview]; 
    } 

    UIViewController* initialScene = [_initalStoryboard instantiateInitialViewController]; 
    self.window.rootViewController = initialScene; 
} 

請注意,在環路中刪除所有子視圖從window。在一個UIWindow RootViewController的文檔指出:

如果窗口有一個現有的視圖層次,老觀點 安裝了新的之前刪除。

但是我沒有發現這種情況......所以我在明確指定一個新的rootViewController之前自己刪除了現有的視圖。我沒有發現使用這種方法的令人擔憂的副作用或內存泄漏。我絕不是UIKit魔術方面的專家,所以我建議你測試一下測試並重新測試這個解決方案,如果你打算自己使用它的話。乾杯

+0

我想試試這個,但並沒有真正展示如何在按下按鈕時從控制器調用函數。 – gdubs 2013-04-14 17:50:44

+2

看看這個SO問題:http://stackoverflow.com/questions/1184146/getting-a-reference-to-the-uiapplication-delegate 它顯示瞭如何獲得對你的應用程序委託的引用 - 在你的情況下你會在你的場景的視圖控制器中使用它。因此,在你的按鈕的觸摸處理程序中,你會得到如下所示的結果: MyApplicationDelegate * appDelegate =(MyApplicationDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate resetWindowToInitialView]; – 2013-04-14 23:16:23

+2

謝謝老闆.... – gdubs 2013-04-15 21:18:55

1

下對我的作品很大,如果你使用基於NavController結構:

UIWindow *window = [[UIApplication sharedApplication].windows firstObject]; 
UINavigationController *navController = (UINavigationController *)window.rootViewController; 
UIViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"Login"]; 
navController.viewControllers = @[vc]; 

您必須分配故事板ID「登錄」您登錄VC爲了這個工作。

0

我下面的作品,如果我用一個UISplitViewController基於結構(在iOS上測試8+):

刪除故事板從項目一般 - >部署信息,所以下拉看起來像下面,你必須在代碼中配置故事板。

Deployment Info Empty Main Interface

某處AppDelegate.m

- (void)setupViewControllers 
{ 
    // check for thread, as this method might be called by other (e.g. logout) logic 
    if ([NSThread currentThread] != [NSThread mainThread]) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self setupViewControllers]; 
     }); 
     return; 
    } 

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 
    UIViewController *vc =[storyboard instantiateInitialViewController]; 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.rootViewController = vc; 

    // configure split vc 
    // Note: I reference split vc for my own purpose, but it is your mater of choice 
    self.splitViewController = (UISplitViewController *)self.window.rootViewController; 
    self.splitViewController.delegate = self; 
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; 
    self.splitViewController.preferredPrimaryColumnWidthFraction = 0.5; 

    [self.window makeKeyAndVisible]; 
} 

爲了避免代碼重複,從application:didFinishLaunchingWithOptions:調用這個函數作爲首次設置

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // some code... 
    [self setupViewControllers]; 
    // Optional: add splash view (e.g. [self addSplashView];) 
    // some code... 
} 

內部的視圖控制器,你準備好向用戶展示UI,刪除飛濺視圖。例如(在斯威夫特):

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 

    if !AppSession.currentSession().isLoggedIn() { 
     presentLoginViewController(false, completion: {()->Void in 
      self.removeSplash() 
     }) 
    } 
    else { 
     removeSplash() 
    } 

    // some code... 
} 

private func removeSplash() { 
    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate { 
     appDelegate.removeSplashView() 
    } 
}