问题
I am building an IOS 5.1 web client app that uses a storyboard. One of my actions is "logout", during which I want to reset my root view to the initial view created by the root view of the Storyboard. (When you log in, some view items are removed or added based on who you are; when you log out, I want to reset them to their default values, which I've specified in the storyboard.)
I realize that I could programmatically reset/re-add all of the elements, but then what good is the storyboard? I figure there's got to be a way to get back to square one by reloading the view file, right?
回答1:
I found the following approach works for me. Please note that I use ARC, unsure if this has much bearing on the solution however. First, in the app delegate class, in application:didFinishLaunchingWithOptions:
I capture the inital Storyboard instance with the following line of code:
_initalStoryboard = self.window.rootViewController.storyboard;
(Obviously there is an instance variable UIStoryboard* _initalStoryboard;
)
Then I have the following function defined in my app delegate:
- (void)resetWindowToInitialView
{
for (UIView* view in self.window.subviews)
{
[view removeFromSuperview];
}
UIViewController* initialScene = [_initalStoryboard instantiateInitialViewController];
self.window.rootViewController = initialScene;
}
Please note the for in loop which removes all subviews from window
. The UIWindow rootViewController documentation states:
If the window has an existing view hierarchy, the old views are removed before the new ones are installed.
However I did not find this to be the case... so I remove the existing views myself explicitly before assigning a new rootViewController. I have not found any worrying side effects or memory leaks using this method. I am by no means an expert on the magic of UIKit so I would suggest you test test and retest this solution if you plan to use it yourself. Cheers
回答2:
The following works great for me, if you use a NavController-based structure:
UIWindow *window = [[UIApplication sharedApplication].windows firstObject];
UINavigationController *navController = (UINavigationController *)window.rootViewController;
UIViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"Login"];
navController.viewControllers = @[vc];
You have to assign the Storyboard ID "Login" to your Login VC in order for this to work.
回答3:
The following works for me, if I use a UISplitViewController
-based structure (tested on iOS 8+):
Remove Storyboard from Projects General -> Deployment Info, so the dropdown looks like the below and you have to configure the storyboard in code.
Somewhere in 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];
}
To avoid code duplicates, call this function from application:didFinishLaunchingWithOptions:
as a first-time setup
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// some code...
[self setupViewControllers];
// Optional: add splash view (e.g. [self addSplashView];)
// some code...
}
Inside a view controller you are ready to present UI to user with, remove splash view. For example (in 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()
}
}
来源:https://stackoverflow.com/questions/10273910/resetting-storyboard-on-logout