Present and dismiss view modally in tabbed application using swift - ios

I've created a tabbed application and am able to present a view modally using the code below, however, I'm stuck on dismissing the view and displaying the tab bar and first view controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let signUpViewController = storyboard.instantiateViewController(withIdentifier:"SignUpViewController") as! SignUpViewController
self.window?.makeKeyAndVisible()
self.window?.rootViewController = signUpViewController

Inside that signUpViewController do this after giving that tabBarController a storyboard identifier in IB
let tab = storyboard!.instantiateViewController(withIdentifier:"tab")
UIApplication.shared.keyWindow?.rootViewController = tab
OR
(UIApplication.shared.delegate as! AppDelegate).window?.rootViewController = tab

You should present your modal vc over you tab bar vc
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let signUpViewController = storyboard.instantiateViewController(withIdentifier:"SignUpViewController") as! SignUpViewController
signUpViewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen
signUpViewController.modalTransitionStyle = UIModalTransitionStyle.coverVertical
self.window.rootViewController.present(myModalViewController, animated: true, completion: nil)
(if self.window.rootViewController - your tab bar view controller)
And in this case you can use dismiss(animated: true, completion: nil) method in modal vc to dismiss it.

In your TabBarViewController, do the following when presenting SignUpViewController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier:"SignUpViewController")
viewController.modalPresentationStyle = .overFullScreen
self.presentViewController(viewController, animated:true)
and when dismissing, simply call the dismiss code from SignUpViewController
e.g. dismissViewControllerAnimated

Related

Push view controller from a Child View controller

From a button action, I have presented a viewController, from that presented VC, add another button and on that button action added a childView like this -
let vc = UIStoryboard(name: "Profile", bundle: nil).instantiateViewController(withIdentifier: "APPopUpViewControllerViewController") as! APPopUpViewControllerViewController
self.addChild(vc)
vc.view.frame = self.view.frame
self.view.addSubview(vc.view)
vc.didMove(toParent: self)
All are working perfectly till now, but when i try to push a viewController from this child VC , it does not work. How can i push a viewController from a childView ??
Push viewController code -
let storyboard = UIStoryboard(name: "WPLogin", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "WPSigninViewController") as! WPSigninViewController
self.navigationController?.pushViewController(vc, animated: true)
My guess is that self.navigationController is nil, so your optional chaining is failing.
You can try
print(parent)
print(parent?.navigationController)
self.parent?.navigationController?.pushViewController(vc, animated: true)
How do you present your ViewController ? If You have pushed it to a navigation controller, then your code is perfect and it should work I think.
If not, then try to present the WPSigninViewController modally as
let storyboard = UIStoryboard(name: "WPLogin", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "WPSigninViewController") as! WPSigninViewController
self.present(vc, animated: true)
and It should work.
If ViewController is your rootController, you can add a NavigationController to it :
let viewController = ViewController(nibName: nil, bundle: nil)
let navigationController = UINavigationController(rootViewController: viewController)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()

Navigation item disappears with popover

I have created a popup displaying a list in which I send the text to another viewcontroller, but when I close the popup, the Navigation Item disappears, and I have already searched for nothing to solve this problem. The code that sends the selected list item in the popover is this:
Shared.shared.filialNome = self.filiais[indexPath.row].razaoSocial
self.recebeCodigo = self.filiais[indexPath.row].codigo
Shared.shared.codigoFilial = self.recebeCodigo
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "AniversarioViewController") as! AniversarioViewController
self.present(newViewController, animated: true, completion: nil)
Type of following = Modal
I have tried to call Present as Popover but the error persists, it seems that it does not close the VC completely, somebody can help me.
Before opening the popover and
After opening the popover
It seems like, as you are presenting the view controller (and ViewControllers do not have navigation item until we embed it in navigation controller).
So you can embed the same ViewController in navigation controller in storyboard and then get the reference for that navigation controller and present the navigation controller like
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navController = storyBoard.instantiateViewController(withIdentifier: "YourNavigationControllerIdentifier") as! UINavigationController
self.present(navController, animated: true, completion: nil)
Or if you don't want to embed you can do programmatically like
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "AniversarioViewController") as! AniversarioViewController
let navController = UINavigationController.init(rootViewController: newViewController)
self.present(navController, animated: true, completion: nil)

Load all views related to tab bar controller by hard code

I would like to jump from a viewController to the first viewController related to Tab Bar Controller through code.
The tabBarController Scene has storyboard id tabView.
I'm working on this way:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: UITabBarController!
storyboard.instantiateViewController(withIdentifier: "tabView")
vc=storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.present(vc as! UIViewController, animated: true, completion: nil)
}
But it loads only the first viewController (out of 5) without the tab bar related to. How can I solve it?
Oh, this code looks so wrong.
In your storyboard give and "tabView" ID to the TabBarController, not the ViewController inside it.
Why you are double instantiating ViewController? just do it once and assign it to the vc variable.
Why you've created delay before presenting the VC? It's some sort of workaround of something?
Working code:
let vc = storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
self.present(vc, animated: true)
Use
(1)if you want to navigate from Appdelegate
let appDelegate = UIApplication.sharedApplication.delegate as! AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBar = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarController") as! TabBarController
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
(2)if you want to navigate from viewcontroller which has root of navigation
self.navigationController?.pushViewController(tabBar, animated: true)

Present a navigationbar and a non root view tabbar controller

I am trying to present the account viewcontroller on other storyboard. But when i present it, the the Tabbar doesn't shows up.
This is my code on the other storyboard that i would like when a button is pressed on the other storyboard it goes to the account viewcontroller (See on the picture) Sorry for my english. Thanks
let storyboard : UIStoryboard = UIStoryboard(name: "UnitedArabEmirates", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "UAE")
self.present(vc, animated: true)
Edit: Sorry for the wrong question. Let me rephrase it. Sorry i am new to programming and swift.
This is my 1st storyboard that when i tapped the "Upload CV" it goes to the the 2nd storyboard and presents my AccountViewController or as it is named identifier as "Account" but when i try to present it, the tabbar that contains the 3 tabbar items doesn't shows up. Just the navigationbar. How can i present the AccountViewController that has a the 3 tabbar items. Thank you so much for your responds.
Here is my first storyboard
Here is my second storyboard
and here is the code that presents my AccountViewController when i tapped the upload CV
let storyboard : UIStoryboard = UIStoryboard(name: "UnitedArabEmirates", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Account")
self.present(vc, animated: true)
let storyboard : UIStoryboard = UIStoryboard(name: "UnitedArabEmirates", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "UAE")
self.navigationcontroller.present(vc, animated: true)
Please try this.
Give ViewController as a NavigationController then present it. It will show the tab bar.
let vc : YourViewController = self.storyboard!.instantiateViewController(withIdentifier: "UAE")as! YourViewController
let navController = UINavigationController(rootViewController: vc) // Creating a navigation controller with VC1 at the root of the navigation stack.
self.present(navController, animated: true, completion: { _ in })

Swift programmatically navigate to another view controller/scene

I'm using following code to programmatically navigate to another ViewController. It works fine, but it some how hides the navigation bar. How do I fix this? (the navigation bar is created by embeding the ViewController in the navigation controller if that matters.)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("nextView") as NextViewController
self.presentViewController(nextViewController, animated:true, completion:nil)
Swift 5
The default modal presentation style is a card. This shows the previous view controller at the top and allows the user to swipe away the presented view controller.
To retain the old style you need to modify the view controller you will be presenting like this:
newViewController.modalPresentationStyle = .fullScreen
This is the same for both programmatically created and storyboard created controllers.
Swift 3
With a programmatically created Controller
If you want to navigate to Controller created Programmatically, then do this:
let newViewController = NewViewController()
self.navigationController?.pushViewController(newViewController, animated: true)
With a StoryBoard created Controller
If you want to navigate to Controller on StoryBoard with Identifier "newViewController", then do this:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
self.present(newViewController, animated: true, completion: nil)
SWIFT 4.x
The Strings in double quotes always confuse me, so I think answer to this question needs some graphical presentation to clear this out.
For a banking app, I have a LoginViewController and a BalanceViewController. Each have their respective screens.
The app starts and shows the Login screen. When login is successful, app opens the Balance screen.
Here is how it looks:
The login success is handled like this:
let storyBoard: UIStoryboard = UIStoryboard(name: "Balance", bundle: nil)
let balanceViewController = storyBoard.instantiateViewController(withIdentifier: "balance") as! BalanceViewController
self.present(balanceViewController, animated: true, completion: nil)
As you can see, the storyboard ID 'balance' in small letters is what goes in the second line of the code, and this is the ID which is defined in the storyboard settings, as in the attached screenshot.
The term 'Balance' with capital 'B' is the name of the storyboard file, which is used in the first line of the code.
We know that using hard coded Strings in code is a very bad practice, but somehow in iOS development it has become a common practice, and Xcode doesn't even warn about them.
You should push the new viewcontroller by using current navigation controller, not present.
self.navigationController.pushViewController(nextViewController, animated: true)
According to #jaiswal Rajan in his answer. You can do a pushViewController like this:
let storyBoard: UIStoryboard = UIStoryboard(name: "NewBotStoryboard", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
self.navigationController?.pushViewController(newViewController, animated: true)
So If you present a view controller it will not show in navigation controller. It will just take complete screen. For this case you have to create another navigation controller and add your nextViewController as root for this and present this new navigationController.
Another way is to just push the view controller.
self.presentViewController(nextViewController, animated:true, completion:nil)
For more info check Apple documentation:-
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/doc/uid/TP40006926-CH3-SW96
OperationQueue.main.addOperation {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "Storyboard ID") as! NewViewController
self.present(newViewController, animated: true, completion: nil)
}
It worked for me when I put the code inside of the OperationQueue.main.addOperation, that will execute in the main thread for me.
All other answers sounds good, I would like to cover my case, where I had to make an animated LaunchScreen, then after 3 to 4 seconds of animation the next task was to move to Home screen. I tried segues, but that created problem for destination view. So at the end I accessed AppDelegates's Window property and I assigned a new NavigationController screen to it,
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let homeVC = storyboard.instantiateViewController(withIdentifier: "HomePageViewController") as! HomePageViewController
//Below's navigationController is useful if u want NavigationController in the destination View
let navigationController = UINavigationController(rootViewController: homeVC)
appDelegate.window!.rootViewController = navigationController
If incase, u don't want navigationController in the destination view then just assign as,
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let homeVC = storyboard.instantiateViewController(withIdentifier: "HomePageViewController") as! HomePageViewController
appDelegate.window!.rootViewController = homeVC
The above code works well but if you want to navigate from an NSObject class, where you can not use self.present:
let storyBoard = UIStoryboard(name:"Main", bundle: nil)
if let conVC = storyBoard.instantiateViewController(withIdentifier: "SoundViewController") as? SoundViewController,
let navController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
navController.pushViewController(conVC, animated: true)
}

Resources