2012-04-23 77 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() 
    } 
}