My app is contained in a UINavigationController
. The root view controller A is essentially a login view, where the user will enter credentials and upon success will present the profile view controller B via a push segue. Right now the user gets the back button on the nav bar of B to navigate back to A . I want B to now be the root view controller on the navigation stack, effectively preventing the user from ever getting back to A until a new app launch.
What is the correct way to handle this while still using a push segue? Should I perform the presentation of B without a segue and effectively start B off with a new navigation controller?
Just replace the rootViewController of your UIWindow
. controllerA and controllerB can be any Viewcontroller
-Class you want.
You could use a simple UITableViewController
for the Loginpage and then replace the rootViewController of your UIWindow
with a UINavigationController
holding controllerB
[UIView transitionFromView:controllerA.view
toView:controllerB.view
duration:0.65f
options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve)
completion:^(BOOL finished){
delegate.window.rootViewController = controllerB;
}];
I know the question is slightly old, but having gone through this myself, I have finally found a solution which I think is better than the accepted answer.
Make the login controller the root controller of the navigation controller.
When login succeeds, remove the login controller from the navigation controllers viewcontrollers array and append your app's initial viewcontroller.
if let navigationController = navigationController { var viewControllers = navigationController.viewControllers for (index, viewController) in viewControllers.enumerated() where viewController is LoginViewController { viewControllers.remove(at: index) } let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main) let initialViewController = storyBoard.instantiateViewController(withIdentifier: "InitialViewController") viewControllers.append(initialViewController) navigationController.setViewControllers(viewControllers, animated: true) }
The only other thing you have to do is add the following line to your initial viewcontroller's viewDidLoad:
navigationItem.hidesBackButton = true
The setViewControllers method with animated set to true takes care of the push animation you specified as a requirement.
EDIT:
I have made a method that can be added to the login controller, which not only works if you want the login controller to be shown as the first view controller in the app, but also if later authentication fails (expired credentials etc.) and you have shown the login controller modally:
func authenticationDidSucceed() {
// If the LoginController is in a navigation stack then
// replace it with the initial viewcontroller of the app
guard navigationController?.viewControllers.contains(self) ?? false else {
// Else it must be presented modally, so dismiss it
dismiss(animated: true, completion: nil)
return
}
guard let navigationController = navigationController else { return }
var viewControllers = navigationController.viewControllers
if let index = viewControllers.index(of: self) {
viewControllers.remove(at: index)
}
viewControllers.append(UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "InitialViewController"))
navigationController.setViewControllers(viewControllers, animated: true)
}
Just remember step 3 from above.
B should be contained in it's own navigation controller since A will no longer be accessible. You'll have to use something other than a push segue. transitionWithView
works well:
UINavigationController *newNavController;
[UIView transitionWithView:delegate.window
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^
{
[delegate.window addSubview:newNavController.view];
}
completion:^(BOOL finished)
{
delegate.window.rootViewController = newNavController;
}];
[delegate.window makeKeyAndVisible];
I was using segue to navigate from a controller A
with navigation to another controller B
, And i wanted to get controller A
deinitialized after the pushing to controller B
so, I would say this was the cleanest and easiest way to remove controller A
in viewDidDisappear
and get it deinitialized.
final class A: UIViewController {
override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.viewControllers.removeAll(where: { self === $0 })
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.