I'm trying to add an UIViewController as child view controller to the tab bar controller. See code below:
guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "MyAlertViewController") as? MyAlertViewController else
{
return
}
let base: UITabBarController = tabBarController!
base.addChildViewController(vc)
vc.view.frame = base.view.bounds
base.view.addSubview(vc.view)
vc.didMove(toParentViewController: base)
It works, but there is an issue that I'm unable to solve: MyAlertViewController is added to tab bar controller's viewControllers array, and sometimes it is even shown as a tab bar item. Is there a way to solve this? Thanks.
Related
I have a LoginView, where after user authentication the user is sent to a corresponding homeView. The transition is made programmatically without segue. Then, depending on the user type (lets say, superuser and tester), the user can browse from his homeView. Both homeViews are preceded by a NavigationController.
NavigationController -Segue-> SuperView -Segue-> SecondView
->LoginView |
NavigationController -Segue-> HomeView <-Segue -
|
-Segue-> View4 -Segue-> View5 ...
Here is the storyboard flow
And the problem: in the simulator, after the login, the first view looks great, but all the next views don't have a navigation bar. In the storyboard, however, everything looks fine.
The transition is made as follows:
func transitionToSuperHome() {
let supervisorViewController = storyboard?.instantiateViewController(identifier: "superVC") as? SuperuserViewController
view.window?.rootViewController = superuserViewController
view.window?.makeKeyAndVisible()
}
and
func transitionToHome() {
let homeViewController = storyboard?.instantiateViewController(identifier: "homeVC") as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
This is how the second (and all subsequent) view looks like
any idea what can cause the problem?
It looks to me like you are setting the root view controller in a detached state. A simple fix might be to embed your root view controller inside of a navigation controller in order to avoid the detached state. This is also why your screenshots appear to be presented modally instead of in a navigation stack.
window?.rootViewController = UINavigationController(rootViewController: homeViewController)
I have 3 view controllers I load from story board :
controller1 = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
controller2 = storyboard.instantiateViewController(withIdentifier: "ModelController") as! ModelController
controller3 = storyboard.instantiateViewController(withIdentifier: "BuyController") as! BuyViewController
I would like to create, and load these 3 controllers into a bottom navigation bar with 3 buttons.
Programmatically .
How would I do that with just a simple few lines of code ?
I made a sample Project for you to do that
Check at - https://drive.google.com/open?id=1M12Nv4PLNUePSJFHf7w8b08M2_mWcUEC
Some refereeing code
My Three VC Objects
private lazy var ThirdObject: VC3 =
{
// Instantiate View Controller
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "VC3") as! VC3
// Add View Controller as Child View Controller
self.addChildViewController(viewController)
return viewController
}()
private lazy var FirstObject: VC1 =
{
// Instantiate View Controller
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "VC1") as! VC1
// Add View Controller as Child View Controller
self.addChildViewController(viewController)
return viewController
}()
private lazy var SecondObject: VC2 =
{
// Instantiate View Controller
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "VC2") as! VC2
// Add View Controller as Child View Controller
self.addChildViewController(viewController)
return viewController
}()
Storyboard View
Simulator screen shots
ScreenShot 1 - When no object added
ScreenShot 2 - When Clicked on any button
I clicked on second So showed as
Note: I had used Toolbar with three button You can do same by adding buttons in Navigation bar , Showed you Method how to do , Depend on you that want to make use of Navigation controller or ToolBar at bottom of screen
I can swap from one UIViewController to another within a UITabBarController using tabBarController?.selectedIndex = targetIndex. I would like to know how to trigger a segue after the switch.
I have tried doing if let vc = tabBarController?.viewControllers?[0] as MyViewController {} and calling vc.performSegue() but it errors out, complaining that it's a UINavigationController. (I couldn't even get vc.prepare() to work but I can't work out how to create a UIStoryBoardSegue, which it requires as the first argument, from scratch using the segue identifier.) I think this is because all of my UIViewControllers in the UITabBarController are within Navigation Controllers.
How do I switch from index 0 to 1 in the tab bar controller, and then trigger a segue in the view controller embedded in the navigation controller? Note, I need to pass in a copy of the calling object (my UIViewController) or a payload for contextual purposes to the UIViewController being segued to.
Well like you said the viewController which is presented at the index is a UINavigationController. You should get the rootViewController of the UINavigationController and perform the Segue on the RootViewController.
Below code should work:
self.tabBarController?.selectedIndex = 1
guard let vc = self.tabBarController?.viewControllers?[1] as? UINavigationController else {
return
}
guard let rootVC = vc.viewControllers.first as? SecondViewController else {
return
}
rootVC.vc = self
rootVC.performSegue(withIdentifier: "test", sender: self)
I created a custom search bar and embedding it in the navigation bar, it appears but after I push another view controller, the search bar does not get replaced with the title of the pushed view controller. The search bar stays persistent throughout all views, instead of getting replaced with a title. Perfect example is Instagram search tab, you search for a person and click on the cell, their profile is pushed and the search bar is replaced with the custom title, back button, etc.
First VC
self.customSearchBar.tag = 4
self.navigationController?.view.addSubview(customSearchBar)
Second VC
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(4) {
searchBar.removeFromSuperview()
}
}
You shouldn't place the searchbar inside the navigationcontroller view as this view is the same instance on all pushed viewcontrollers.
Add the searchbar to the the depending view controllers ui.
To add a searchbar on navigationBar, this is the way.
self.navigationController?.navigationBar.addSubview(customSearchBar)
To remove it when you push it to other viewController. Write the following code in the secondVC that is pushed inside it's viewDidLoad() function. Also, set the tag of customSearchBar to any number (TAG)
if let nav: UINavigationController = self.navigationController {
let bar: UINavigationBar = nav.navigationBar
if let searchBar = bar.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
In the question, the customSearchBar is added to self.navigationController.view. To remove it, you can do the following:
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
Edit:
Adding and removing a UIViewController's view as a subview of other UIViewController
// for adding
let viewController: ViewController = ViewController()
self.addChildViewController(viewController)
self.view.addSubview(viewController.view)
viewController.view.bounds = self.view.bounds // better to use autolayout here
viewController.didMove(toParentViewController: self)
// for removing
if let vc = self.childViewControllers.last {
vc.willMove(toParentViewController: nil)
vc.view.removeFromSuperview()
vc.removeFromParentViewController()
}
I am trying to add both a Navigation Bar Controller and a Tab Bar Controller to my application.
"First View Controller" is my first View Controller at index 0.
However, I cannot embed a Navigation Controller into First VC without incurring an error:
Could not cast value of type 'UINavigationController' (0x1a0a21fb8) to 'project.FirstViewController' (0x1000ae228).
Here's the code in my App Delegate:
let TabBarController = self.window!.rootViewController as! UITabBarController
let controller = TabBarController.viewControllers![0] as! FirstViewController
controller.managedObjectContext = self.managedObjectContext
I realize that there is no Navigation Controller object in my code. Should the Tab Bar Controller NOT be behind the login page?
Obviously I plan on using both a Navigation Controller and Tab Bar Controller post-login.
But how do I instantiate a Navigation Controller to have a Navigation Bar in my First VC?
Thank you
Your Storyboard should look like this image
add navigation controller
this may help
You are actually almost there. From what I can read, the error states that it is unable to cast FirstViewController into UINavigationController. Assuming that your storyboard looks like the one in #PKT's answer, your codes should look like this.
let TabBarController = self.window!.rootViewController as! UITabBarController
let navigationController = TabBarController.viewControllers![0] as! UINavigationController
let controller = navigationController.topViewController as! FirstViewController
controller.managedObjectContext = self.managedObjectContext
The NavigationController is important if you want to NavigationBar. though.