I am using Xib instead of storyboard and using this code in my AppDelegate to perform navigation in my project
var nav = UINavigationController()
let FirstVC = HomeScreenVIewController(nibName: "HomeScreenVIewController", bundle: nil) as HomeScreenVIewController
nav = UINavigationController(rootViewController: FirstVC)
nav.navigationBarHidden = true
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
nav.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
To navigate from one view to other on button click I am using this code
let NextVc = RegistrationStepOneViewController(nibName: "RegistrationStepOneViewController", bundle: nil) as RegistrationStepOneViewController
appDelegate.nav.pushViewController(NextVc, animated: true)
This navigation will go for all registration process steps. When registration is completed there is a dashboard screen from where user can not navigate back to registration steps(obviously).
Now I want another navigation to start from dashboard and go futher in the application. How can I do that ?
Thanks in advance :-)
You can use the setViewControllers: animated: method to replace the current navigation stack with whatever stack you'd like.
self.navigationController?.setViewControllers([yourNewRootVC], animated: true)
The above, for example, would give you a new root controller and would blow up your current nav stack.
Having said that, with the situation you are describing, I would recommend launching the app with the main view controller as the root of your nav VC, then presenting (animated: false) the registration flow over that. Then you just need to dismiss it once registration is complete or not present it at all if registration has already happened. Hope that makes sense!
You can do something like,
let vc: UIViewController = UIViewController()
let view: UIView = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))
vc.view = view
vc.view.backgroundColor = UIColor.orangeColor()
let arr: [UIViewController] = [vc as UIViewController]
self.navigationController!.setViewControllers(arr, animated: true)
You can set array of viewcontrollers to navigation controller. You can add multiple array to that arr and can use same navigation controller.
Related
I want to append couple of viewcontrollers in array of viewcontroller of a navigation controller, then want push third viewcontroller of the same navigation controller.
My code is as follows
let navigationController = getCurrentNavController()
let listVC = UIStoryboard.loadListViewController()
navigationController.viewControllers.append(listVC)
let detailVC = UIStoryboard.loadDetailsViewController()
navigationController.viewControllers.append(detailVC)
let thirdVC = UIStoryboard.loadThird()
navigationController.pushViewController(thirdVC, animated: true)
The thirdVC is push on the navigation controller,
the problem is when i pop thirdVC,
I don't find detailVC or listVC.
Is this possible?
if yes please help.
Don't edit the viewControllers array directly. That is why the animated parameter exists.
A solution may be to add the viewControllers in between after 0.25 seconds (the duration of the push animation) by doing:
let navigationController = getCurrentNavController()
var viewControllers = navigationController.viewControllers
let listVC = UIStoryboard.loadListViewController()
viewControllers.append(listVC)
let detailVC = UIStoryboard.loadDetailsViewController()
viewControllers.append(detailVC)
let thirdVC = UIStoryboard.loadThird()
viewControllers.append(thirdVC)
navigationController.pushViewController(thirdVC, animated: true)
DispatchQueue.main.asyncAfter(now() + 0.25) {
navigationController.setViewControllers(viewControllers, animated: false)
}
As mentioned, you do not want to modify the navigation controller's viewControllers directly.
But, you also don't need to do any explicit "pushing":
let navigationController = getCurrentNavController()
let listVC = UIStoryboard.loadListViewController()
let detailVC = UIStoryboard.loadDetailsViewController()
let thirdVC = UIStoryboard.loadThird()
var vcs = navigationController.viewControllers
vcs.append(listVC)
vcs.append(detailVC)
vcs.append(thirdVC)
navigationController.setViewControllers(viewControllers, animated: true)
This will animate thirdVC in from the current view controller, just as if you had pushed it, but it will also insert listVC and detailVC into the navigation controller's stack so the "Back" button will take you through detailVC and listVC.
I have a weird behavior when presenting UIViewControllers modally in iOS 13. The new presentation style that I've seen all across iOS 13 looks like this:
The presenting view controller appears behind the presented view controller. It is also shifted down to mimic a "stack"
Meanwhile, when presenting view controllers through my app, I keep getting this effect:
The presenting view controller doesn't move at all when presenting a new view controller
I use this code to present this view controller:
let controller = storyboard?.instantiateViewController(withIdentifier: "tutorial") as! TutorialController
controller.modalPresentationStyle = .pageSheet
controller.modalTransitionStyle = .coverVertical
present(controller, animated: true, completion: nil)
Here is my question:
I'm wondering why this is happening and if there is a way to present view controllers in the normal iOS 13 style (with the presenting view controller moving back).
Thanks in advance!
Turns out the problem was my view controller hierarchy. I was able to fix it by making the presenting view controller the root view controller of my app. First I set the background controller as the root view controller by calling
window.rootViewController = self
and then using my previous code
let controller = storyboard?.instantiateViewController(withIdentifier: "tutorial") as! TutorialController
controller.modalPresentationStyle = .pageSheet
controller.modalTransitionStyle = .coverVertical
present(controller, animated: true, completion: nil)
I presented the view controller. Thanks to everyone who tried to help!
I think the issue can be resolved by using vc.modalPresentationStyle = .fullScreen if there is not UINavigationController , otherwise you can use these codes as follows:
let navigationController = UINavigationController(rootViewController: vc)
navigationController.modalPresentationStyle = .fullScreen
present(vc, animated: true)
because With iOS 13 this is a new feature that Apple has changed the default presentation style of View Controllers to a modal sheet from fullscreen in iOS 12
Programmatically:
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
From storyboard:
That's it. No need to play with root controller or window at all.
For reference, visit this article.
iOS13: Let's say you have 3 view controllers: FirstVC, SecondVC, ThirdVC
FirstVC presents SecondVC with the below code:
let secondVC = SecondVC()
secondVC.modalPresentationStyle = .fullScreen
firstVC.present(secondVC, animated: true, completion: nil)
SecondVC presents ThirdVC with the below code:
let thirdVC = ThirdVC()
secondVC.present(thirdVC, animated: true, completion: nil)
Changing secondVC's modalPresentationStyle to .currentContext solves the problem.
We can change it in the Inspector Tool Bar. To Achieve it: head over to the fifth section of Inspector Tollbar then change the Presentation field to Full Screen.
This should be the only property you need to set
presentedViewController.modalPresentationStyle = .automatic
Detailed in
https://developer.apple.com/videos/play/wwdc2019/224/
I've following view configuration
Tab bar -> Nav controller -> View: Click on a button -> segue to-> Another view: Click on a button -> Popup view.
This modal view is on a different storyboard.
I want to present this model view in full screen. I've tried this solution mentioned on Presenting modal in iOS 13 fullscreen but it doesn't work. I've also tried few other solutions but the popup view is not showing over full screen, status bar is visible at the top.
How do I present modal view in a full screen?
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
popupVC.modalPresentationStyle = .fullScreen
self.present(popupVC, animated: true, completion: nil)
You could try presenting with the navigation controller.
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
var navigationController = UINavigationController(rootViewController: popupVC)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationViewController, animated: true, completion: nil)
An alternative would be to use presentViewController but presentViewController will only present one viewController modally over the currently visible viewController whereas presenting with the navigationController will give the flexibility to push further components on top, providing a smoother navigation experience with go back to previous page kind of behaviour.
Maybe try creating the view controller this way:
let popOverVC = UIStoryboard(name: "yourBoard", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
self.addChild(popOverVC)
let lSs = UIScreen.main.bounds
popOverVC.view.frame = CGRect(x: 0, y: 0, width: lSs.width, height: lSs.height)
popOverVC.view.tag = tag
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParent: self)
Within the popup view controller class, add a method for animating its view in viewDidLoad.
Edit: I read your replies. The issue you are having is caused by not handling the status bar properly. Instead of trying to make this veiewcontroller fullscreen, simply hide the status bar
How do I hide the status bar in a Swift iOS app?
and bring it back when you want to see it again.
I am setting up the side menu by following SideMenu
When the app is loaded first the side menu controller is working fine (.menuslide)
but when I come back to the same controller from the side menu to the same view controller or any other controller or any other page it is not following (.menuslide)
I have tried by assigning the navigation
let menu = SideMenuNavigationController(rootViewController: YourViewController)
let rightMenuNavigationController = SideMenuNavigationController(rootViewController: YourViewController)
SideMenuManager.default.rightMenuNavigationController = rightMenuNavigationController
present(menu, animated: true, completion: nil)
through code and also
From the story board
I am navigating from every controller to side menu like this
let navigationController = storyboard!.instantiateViewController(withIdentifier: "sidemenunavigation") as! SideMenuNavigationController present(navigationController, animated: true, completion: nil)
for the first time after loading it is navigating properly (.menuslide)
but after navigating to other controller and get the side menu it is not following (.menuslide)
you may use the following RESideMenu for side menu quite easy to use
RESideMenu for side menu
please check this code is working fine for navigation another view controller for sidemenu
let storyBoard = UIStoryboard(name:"Main", bundle: nil)
if let conVC = storyBoard.instantiateViewController(withIdentifier: "RoutingAddViewController") as? RoutingAddViewController,
let navController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
navController.pushViewController(conVC, animated: true)
}
how could i dismiss a view controller that i call it by using this method
func openUpgradeAccount(){
let appdel = AppDelegate.sharedInstance()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let earnFreeSpace = storyboard.instantiateViewControllerWithIdentifier("IAPUpgradeVC") as! IAPUpgradeVC
let navigation:UINavigationController = UINavigationController(rootViewController: earnFreeSpace)
appdel.drawerController!.mainViewController = navigation
appdel.drawerController!.setDrawerState(.Closed, animated: true)
}
in this controller i add UIBarButtonItem to cancel id viewdidload method
let cancelBarBtn = UIBarButtonItem(title: NSLocalizedString("Cancel", tableName: appLocalizedTable, comment: ""), style: UIBarButtonItemStyle.Done, target: self, action: #selector(IAPUpgradeVC.didTapCancelButton(_:)))
cancelBarBtn.tintColor = UIColor.whiteColor()
self.navigationItem.leftBarButtonItem = cancelBarBtn
the didTapCancelButton method that i use to dismiss the view was
func didTapCancelButton(sender: UIBarButtonItem) {
self.dismissViewControllerAnimated(true) { () -> Void in
}
but when i tap cancel button nothing happen , what i want how can i return back to the last ViewController , can anyone help me ?
First of all, what is the drawerController? What's its superclass and what's its mainViewController supposed to be?
The method that you call when tapping the button is for dismissing a view controller presented modally. However before that, you do not present that view controller modally, setting is as drawerController's mainViewController instead:
appdel.drawerController!.mainViewController = navigation
One way to make it work is to change this line, so that instead of setting mainViewController you call presentViewController to present the new view controller modally.
If that is not how you want it to work (no presentation of view controllers), you'd have to elaborate on what you want both the new vc and the drawerController to do.