20

我正在构建一个使用情节提要的 IOS 5.1 Web 客户端应用程序。我的操作之一是“注销”,在此期间我想将我的根视图重置为由情节提要的根视图创建的初始视图。(当你登录时,一些视图项会根据你的身份被删除或添加;当你注销时,我想将它们重置为我在故事板中指定的默认值。)

我意识到我可以以编程方式重置/重新添加所有元素,但是故事板有什么用呢?我认为必须有一种方法可以通过重新加载视图文件来恢复原状,对吗?

4

3 回答 3

28

我发现以下方法对我有用。请注意,我使用 ARC,但不确定这是否对解决方案有很大影响。首先,在应用程序委托类中,application:didFinishLaunchingWithOptions:我使用以下代码行捕获初始 Storyboard 实例:

_initalStoryboard = self.window.rootViewController.storyboard;

(显然有一个实例变量UIStoryboard* _initalStoryboard;

然后我在我的应用程序委托中定义了以下函数:

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

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

请注意 for in 循环从window. UIWindow rootViewController 文档指出:

如果窗口具有现有的视图层次结构,则在安装新视图之前删除旧视图。

但是我没有发现这种情况......所以我在分配一个新的 rootViewController 之前明确地删除了现有的视图。使用这种方法,我没有发现任何令人担忧的副作用或内存泄漏。我绝不是 UIKit 魔法方面的专家,所以如果你打算自己使用它,我建议你测试并重新测试这个解决方案。干杯

于 2012-09-10T04:39:47.867 回答
2

如果您使用基于 NavController 的结构,以下内容对我很有用:

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

您必须将 Storyboard ID“登录”分配给您的登录 VC,才能使其正常工作。

于 2014-08-23T18:49:25.640 回答
0

如果我使用UISplitViewController基于 - 的结构(在 iOS 8+ 上测试),则以下内容对我有用:

从 Projects General -> Deployment Info中删除 Storyboard ,因此下拉列表如下所示,您必须在代码中配置 Storyboard。

部署信息空主界面

在某处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,删除启动视图。例如(在 Swift 中):

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()
    }
}
于 2015-11-24T10:06:18.170 回答