Segue from modal view to tab bar view controller and not lose tab bar
Here is my example of how to do this. In my setup, I choose the yellow ViewController from the tab, then press Go! which modally presents the white ViewController. Pressing Exit returns to the green ViewController.
To set this up, use an unwind segue to return to the viewController that called you. For instance, implement this in the first ViewController of the tab (the one calling the modal segue).
@IBAction func backFromModal(_ segue: UIStoryboardSegue) {
print("and we are back")
// Switch to the second tab (tabs are numbered 0, 1, 2)
self.tabBarController?.selectedIndex = 1
}
Then switch to another tab using self.tabBarController?.selectedIndex = n
where n
is the number of the tab you really want to go to. To set up the unwind segue, you can either control-drag from a button in your modal view controller to the exit icon at the top of the viewController and select backFromModal
from the pop up...
OR
you can set up the unwind segue to be called programmatically by control-dragging from the viewController icon at the top of the modal viewController to the exit icon, and select backFromModal
from the pop up.
Then, go to the Document Outline View and click on the unwind segue
and give it an identifier in the Attributes Inspector on the right (for example "returnFromModal"
).
Then you'd call the unwind segue like this:
self.performSegue(withIdentifier: "returnFromModal", sender: self)
Tab bar disappears when returning from modal view controller
The only solution I could find that worked was to remove all modal segues. I switched them all over to "show" segues and haven't had a problem since. Must be something to do with the fact that I was not displaying the modal views full screen. I still had the tab bar on the bottom. When transitioning from the modal view back to the caller, there would often be a flash of colours at the tab bar, then sometimes the tab bar would come back, and other times it would be covered by the background.
How to segue modal without losing tab bar controller
You don't need a separate modal Segue back to the Second View Controller, you can just dismiss the modal view controller when "Back to Second View" is clicked
[self dismissModalViewControllerAnimated:YES];
How can I segue to the second tab of a tab bar controller from the first tab?
You don't want to segue. A segue creates a new instance of the destination view controller and presents it.
That's why your tab bar is disappearing. You are covering your tab bar controller, with it's 2 tabs, with a new instance of your TabBarController2.
You want to switch to the other tab.
What you want to do is to ask your owning tab bar controller to switch tabs.
UIViewController
has a property tabBarController that lets you get to your owning tab bar controller.
TabBarControllers have a property selectedIndex
that let you select one of a tab bar controller's view controllers to become the active view controller.
So, send a message to your tab bar controller asking it to switch to the other tab.
EDIT:
Other people aside from the OP have asked for sample code illustrating how to do this. I decided to create a sample project illustrating how to do it.
You can download it from Github: https://github.com/DuncanMC/TabBarControllers.git
I created a base class of UIViewController ATabController
for the view controllers that are managed by the tab bar controller. The ATabController.swift
file includes an enum to indicate which tab you want to select:
@objc enum Tab: Int {
case first = 0
case second
case third
}
(Note that the enum has to be an Objective-C enum if you're going to pass parameters of type Tab
to IBActions, since IBAction methods need to use Objective-C types and function signatures.)
It also includes a protocol TabController
:
@objc protocol TabController {
@objc func switchTab(to: Tab)
}
It also defines a delegate tabDelegate
:
weak var tabDelegate: TabController?
The tab bar controller has a prepareForSegue (prepare(for:sender:)
) that it uses to make itself the tabDelegate
of all the view controllers it manages as tabs:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let child = segue.destination as? ATabController {
child.tabDelegate = self
}
And then it implements the switchTab(to:)
method:
@objc func switchTab(to: Tab) {
let index = to.rawValue
guard let viewControllerCount = viewControllers?.count,
index >= 0 && index < viewControllerCount else { return }
selectedIndex = index
}
In any of the child view controllers that are tabs of the tab bar controller, you can use IBAction
code like this to switch tabs:
@IBAction func handleFirstButton(_ sender: Any) {
tabDelegate?.switchTab(to: .first)
}
How to retain tab bar after modal segue?
Does your views (the views of the 3 views controller) contain the tab bar? If not, you may try transiting from the view to the view of the extra view controller.
see +[UIView transitionFromView:toView:duration:options:completion:]
How within a tab bar controller do I segue from one view controller to another and retain the tab bar?
From your explanation, I don't think you want a modal controller. Modal is used to overlay, rendering your tab bar useless. From your storyboard, select your segue and select push, not modal.
Push vs Modal (Note the tab bar):
Perform segue to another Navigation Controller without showing Tab Bar
You can simply set the hidden
property of your tab bar when the stop schedule view controller is displayed and unhide the tab bar before that view controller disappears
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden=true
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.tabBarController?.tabBar.hidden=false
}
Update: To animate the transition you can use this:
class StopViewController: UIViewController {
var barFrame:CGRect?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// self.tabBarController?.tabBar.hidden=true
if let tabBar=self.tabBarController?.tabBar {
self.barFrame=tabBar.frame
UIView.animateWithDuration(0.3, animations: { () -> Void in
let newBarFrame=CGRectMake(self.barFrame!.origin.x, self.view.frame.size.height, self.barFrame!.size.width, self.barFrame!.size.height)
tabBar.frame=newBarFrame
}, completion: { (Bool) -> Void in
tabBar.hidden=true
})
}
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.tabBarController?.tabBar.hidden=false;
if self.barFrame != nil {
UIView.animateWithDuration(0.3, animations: { () -> Void in
let newBarFrame=CGRectMake(self.barFrame!.origin.x, self.view.frame.size.height-self.barFrame!.size.height, self.view.frame.size.width, self.barFrame!.size.height)
self.tabBarController?.tabBar.frame=newBarFrame
})
}
}
}
Related Topics
Strange Swift Numbers Type Casting
How to Make a Weak Protocol Reference in 'Pure' Swift (Without @Objc)
Opt Out of Uiscenedelegate/Swiftui on Ios
What's the Difference Between "As", "As!", and "As"
Firestore Search Array Contains For Multiple Values
Cfrunloop in Swift Command Line Program
How to Convert Unix Epoch Time to Date and Time in iOS Swift
What Is the "Some" Keyword in Swift(Ui)
Input from the Keyboard in Command Line Application
How to Hash Nsstring With Sha1 in Swift
How to Unwrap an Optional Value from Any Type
Tabview Resets Navigation Stack When Switching Tabs
How to Use Userdefaults With Swiftui
What Is Difference Between Optional and Decodeifpresent When Using Decodable For Json Parsing
How Does Collisionbitmask Work? Swift/Spritekit
How to Remove the Left and Right Padding of a List in Swiftui
How to Use Instance Method as Callback For Function Which Takes Only Func or Literal Closure