Swift - TabBarController -> ViewController -> NavigationController - ios

i have the following situation:
I got a TabBarController with some tabs(ViewControllers).
When i am in one of these ViewControllers, i tap a button and i want to segue to a NavigationController AND still see the tabbar...
Here is what i did:
I created a new ViewController(DetailViewController)
I embedded this new ViewController(DetailViewController) in a NavigationController
I created a segue(Show) from the "viewcontroller which is embedded in the tabbarcontroller" to the "new navigationcontroller"
I coded:
func buttonTapped {
performSegue(withIdentifier: "shownavicontroller", sender: nil
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationNavigationController = segue.destination as! UINavigationController
let targetController = destinationNavigationController.topViewController as! DetailViewController
}
What goes wrong:
NavigationController is sliding from bottom to top... it should slide from left to right
BackButton in NavigationController is missing
TabBar in NavigationController is missing...
Anybody could help me with this issue?
Thanks and Greetings!!

You have done wrong.
You should not embed UIViewController directly to tabBarController to get the desired result you want.
From Storybaord,
If you are designing your application from storyboard then you should add a UIViewController and embed this UIViewController object into UINavigationController and then embed this NavigationController in a UITabBarController. So that if a button in above UIViewController is pressed and you need to open an other UIViewController not form Bottom to Top but from Left to Right and expecting a Automatic back button at top bar and hide bottom bar.
Then you need to create a Push/Show Segue form Above ViewController (Embed in NavigationController -> Embed in TabBarController) to you new UIViewController that will open.
And before calling the push/show segue you need to write bellow lines.
self.tabBarController?.hidesBottomBarWhenPushed = true

According to your question i believe this is what you need:

Related

How to do a performSegue to a specific view in Tab Bar Controller from another view (swift 4)

In my iOS app, in a viewController I try to open a specific view in Tab Bar Controller.
I use a performSegue.
First I try to navigate straight to the specific view , but in this case the tab bar disappear
So I try to navigate to the tabViewController, and this lead me to the defult view (the first)
any idea how to navigate to a specific view in TabBarController ?
the performSegue I use:
self.performSegue(withIdentifier: "goToMain", sender: self)
//"goToMain" is my indentipier to the storyboard Segue
I use swift 4
with this code, you don't need segues, you can use when you push some button
let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "tabBarController") as! tabBarLoginViewController
VC1.selectedIndex = 2 //this line says that the view that appears will be third of you tab bar controller
self.navigationController!.pushViewController(VC1, animated: true)
if you want to use segue use this, the segue needs to point of tab bar controller, not a view of tab bar controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "goToMain") {
let vc = segue.destination as! TabBarController
vc.selectedIndex = 2
}
}

How to pass the data to next View via Segue in Swift?

I am developing in Swift.
And the following picture is my storyboard.
There has a Main view. The Main view will change the view to the Scan view and also pass the data to the Scan view when press the Scan (Right Bar button item).
And the identifier of the StoryBoard Segue is ScanView
I use the following code to pass the data from Main to the Scan
When press the Scan (Right Bar button item).
self.performSegueWithIdentifier("ScanView", sender: self)
And pass the data to the next view
//prepare jumping to next page
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier=="ScanView"){
let desViewController = segue.destinationViewController as! ScanViewController
desViewController.myCenteralManager = myCenteralManager
}
}
And it will crash at let desViewController = segue.destinationViewController as! ScanViewController and show the error like the following :
Could not cast value of type 'UINavigationController' (0x3960e0a8) to 'BLEConnect.ViewController' (0x5514c).
Can someone teach me how to solve the issue ? Thanks in advance.
The error message are pretty clear, you try to get segue.destinationViewController as ScanViewController while in fact it is a navigation controller. You need to get the navigation controller first and then use its topViewController property to get your targeted view controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier=="ScanView") {
if let navController: UINavigationController = segue.destinationViewController as? UINavigationController {
if let desViewController: ScanViewController = navController.topViewController as? ScanViewController {
desViewController.myCenteralManager = myCenteralManager
}
}
}
}
Your NavigationController is (probably) in the wrong place in Interface Builder. Right now, when you segue, you are going to the UINavigationController and not the ScanViewController like you expect. This is why the cast fails, because you are trying to force the UINavigationController to be a ScanViewController.
To fix this, you should place your MainViewController in the UINavigationController and then segue straight to your ScanViewController.
This guide shows exactly how you can use Interface Builder, UINavigationController, and segues to achieve what you're trying to do.
You can embed your navigation controller to the main ViewController and perform a segue as you have done above. That should solve the problem.
The error message is displayed because you have type casted Navigation Controller instead of Scan ViewController .

Segue between Navigationcontroller and Tableviewcontroller

I have 3 view controllers. First: NavigationController, Second: TableViewController and Third: DetailsTableViewController (connected respectively)
And then I need to add a custom top bar buttton to DetailsTableViewController but I can't. Because there is no NavigationController before the DetailsTableViewController. When I add a NavigationController between TableViewController and DetailsTableViewController, I can't figure out how to fix my code working again.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestEntryDetailedTableViewController : DetailsTableViewController = segue.destinationViewController as! DetailsTableViewController }
What's the best and acceptable way of doing this? How to connect direktly a connection between TableViewController and DetailsTableViewController?
Note: DetailsTableViewController is not detail view of TableViewController. It just another UITableViewController instance.

Unwind segue hides UITabBar using Swift

Good afternoon,
I'm trying to perform an Unwind segue from a ViewController to the parentViewController, but for some reason it's working but instead of showing the parentViewController wit the UITabBar (because everything is inside a TabBarController) it's showing the parentViewController without the UITabBar.
The question is: How can I perform an "unwind segue" and make visible the UITabBar in my parentViewController?
I perform the first segue (from parent to ViewController) using a segue "present modally" with "current context", and I use this because I need to show the UITabBar also in the ViewController.
That's my first segue (from parent to ViewController):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "showPost" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let navVC = segue.destinationViewController as! UINavigationController
let childVC = navVC.viewControllers.first as! PostViewController
childVC.id_post = posts[indexPath.row].idPost
}
}
}
And that's my unwind segue:
#IBAction func backToPosts(segue:UIStoryboardSegue) {}
Here you are and screenshot of my Storyboard:
Thanks in advance,
Regards.
Try in the viewDidLoad tabBarController.tabBar.hidden = false
have you tried theController.hidesBottomBarWhenPushed
If someone is having the same problem:
I removed the NavigationController after the TabBarController.
Regards

Swift: Segue(modal) to a UITableViewController which embeded in antoher navigation controller

Background: I want to display a modal segue from a UITableViewController(A) to a UITableViewController(B), but I want to show a NavigationBar to "Cancel" and "Save".
What I've done:
In storyboard:
I ctrl drag the cell from A to B, and set segue identifer "selectItem"
I choose B and select "Editor - Embed in - Navigation Controller"
In A's ViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifer == "selectItem" {
if let indexPath = self.tableView.indexPathForSelectedRow() {
let destinationViewController = segue.destinationViewController as B
// Pass value from A to B
}
}
}
Error:The app crashed at let destinationViewController = segue.destinationViewController as B with the error swift_dynamicCastClassUnconditional. If I didn't embed a navigation controller to B, the program would not crash. But I really need a navigation bar.
Is there any solution or other way to achieve this? Thank you!
PS: I tried drag a NavigationBar from object library in storyboard, but it's miss a part of background to cover statusbar...
Create both of the UITableViewController in your storyboard.
Select your Second UITableViewController (the one you want to present modally), and embed it in an UINavigationController.
Add the "Cancel" and "Save" UIBarButtonItem into UINavitionItem of the Second UITableViewController.
Select the UITablViewCell of your First UITableViewController
Control+Drag into your UINavigationController.
Select "Present Modally" under the "Selecteion Segue" option from the dropdown list.
To pass data in your First UITableViewController override the method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "identifier" {
let destination = segue.destinationViewController as UINavigationController
let bViewController = destination.topViewController as BViewController
// pass data
}
}
Here are the screenshots:
This should do the job, Cheers!
I solved it!
I added a BreakPoint at the line let dest = segue.destinationViewController as B, and I found that segue.destinationViewController is NavigationController type. So I fixed it by replacing this line to:
let dest = segue.destinationViewController as UINavigationController
let bVC = dest.topViewController as B
and do some passing value stuff.
Hope this will help other people facing this problem.
I use
if let b = segue.destinationViewController.childViewControllers.first as? B {
//do something with b
}
for this scenario. It is really just a syntax difference though.

Resources