How to show the tab bar when using Segue back in swift - ios

I have a Tab bar in the first view and a total of two views.
However, when I move from the first view to the second view and then back to the first view using the Segue, the Tab bar of the first view disappears.
When return to the first view from the second view, what is the way the Tab bar does not disappear?(without using unwind)

Don't use unwind segue here. When you need to get back to previous ViewController, just dismiss your current ViewController
dismiss(animated: true, completion: nil) /* call this in second VC */

I suggest you read the documentation for understanding how combined View Controller Interfaces. Anyway, if you need to pop to previous view controller on the flow, you need to use
navController.popViewController(animated: true)
But, if the need to pop up on the specific ViewController on the queue of View Controllers in the NavigationViewController, you need to use
navController.popToViewController(ViewController, animated: true)
From the moment you are using a NavigationController, a return button will automatically appear on the UINavigationBar, so you do not have to worry about that. Unless you want to customize the back buttons in the viewcontrollers queue, in this case use the above methods.

It's for page 1. Display tabBarController once page is loaded.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden = true
}
If click event is fired, hide tabBarController.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "twoSegue") {
self.tabBarController?.tabBar.hidden = false
}
}

Related

Back Button with Multiple Sources

Within my app, I want to create a user profile controller, which can be navigated to from several different controllers. I would like it to have a back button that will take the user back to whichever controller they came from.
How do I do this?
Dismiss
Add UIButton for back navigation somewhere to your UserProfileController. Then in UserProfileController create action and set it as action of your button. This action dismisses your UserProfileController (so you get back to previous UIViewController)
#IBAction func backButtonPressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
UINavigationController
Alternatively you can have previous ViewControllers embed in UINavigationController. Then you will be able to tap to back button (which is set by default) in UINavigationBar which gets you to previous UIViewController

Why tab bar is missing after presenting a new view controller?

I have created a simple tab bar with three views in storyboard. The tab bar works well, but when I try to show another view controller from a button within a tab, the new view is placed over the whole screen and also over the tab bar.
This is how I present the view so far when a button is pressed:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.present(newVC!, animated: true, completion: nil)
}
The other idea I had was this:
self.tabBarController?.present(vc!, animated: true, completion: nil)
But this didn't work either.
So how can I present another view controller within the tab bar (so that the bottom bar is still shown)?
When you present a view controller modally, its presentation style will be "Full Screen" by default. What you want to do is have it do in this case is just cover part of the screen (the part where the presenting view controller is drawn.
One way to accomplish this is to:
Set the modalPresentationStyle for the presented view controller to be .currentContext or .overCurrentContext
In the view controller that will be presenting the modal, set its definesContext property to true.
These steps can be done either in Interface Builder by setting attributes on the segue and the view controller, or you can modify your code to include the following:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.definesPresentationContext = true
newVC?.modalPresentationStyle = .overCurrentContext
self.present(newVC!, animated: true, completion: nil)
}
What this combination of properties does is:
Indicate for the presented view controller that you want it to be presented in a non-full screen context (some specific section of the screen)
Indicate that the presenting view controller is in the section of the screen / the context you want the modal to be drawn according to.
More details can be found in the Apple Documentation
When you are using present method, the ViewController is presented modally and covers your UITabBarConntroller. Instead of showing your view modally you can embed every first view controller in your TabBar into UINavigationController and then use method pushViewController to push it onto stack. You will have your TabBar visible and nice looking animation for free.
In Xcode, I created a new project using the Tabbed App template to illustrate the solution above. This will create a project with a tabbar controller and two view controllers. I added a button with the title "view page" to the first view controller and embedded a navigation controller from the storyboard.
The storyboard will look like this after making the above changes:
In the FirstViewController.swift file, I created an IBAction for the button with the following code that will create another view controller called DetailViewController, with the title Favorites and a background color of orange. I used the navigation controller to present it by pushing it onto the navigation controller stack.
#IBAction func viewPageButtonTapped(_ sender: UIButton) {
print("viewPageButtonTapped")
let pinkViewController = DetailViewController()
pinkViewController.title = "Favorites"
pinkViewController.view.backgroundColor = UIColor.orange
navigationController?.pushViewController(pinkViewController, animated: true)
}
When I run the project on the simulator, I got the desired result. Hope this helps give you some ideas.
In your viewController do:
self.tabBarController?.present(nextViewController, animated: true/false, completion: {})

Reset tabBar.isHidden doesn't work in viewWillAppear

The sequence is tabBarController->navigationController->viewController->viewController
I wrote the following code in the second viewController.
When the user comes to the second viewController, I want to hide the tab bar.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tabBarController?.tabBar.isHidden = true
}
When the user clicks "Cancel" button, I want to go back to the main page.
#IBAction func cancelAction(_ sender: Any) {
// Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
self.navigationController?.popToRootViewController(animated: true)
}
After go back to the first viewController, I want to make the tab bar show again.
override func viewWillAppear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
}
But in fact, the tab doesn't show at all. And the page suddenly shakes for a moment. Don't know why.
Remove all your code for setting Tab bar, and try this option for Second View Controller in XIB or Storyboard:

iOS Storyboard presenting tab bar modally vs push in XCode 8

Consider a storyboard where we have UITabBarController, in it any UIViewController(lets call it VC) embedded in a UINavigationController. We want VC to have a BarButtonItems on its navigation bar. This storyboard is presented by push segue from another storyboard (having another navigation controller).
Everything looks OK in XCode, but navigation bar does not change in VC at the runtime. However when I change presenting this storyboard from push to modal, everything seems to be fine. IMHO it is because of embedding the navigation controller but I do not see any reason why it is not working. Any idea how to fix it legally (presenting by push) and without any pain would be helpful.
Thanks in advance
So I think you will have to employ some code to fix your issue but not much. I built a test project to test this and will attach images along with code.
First if I understand you correctly you have a navigationController push the new storyboard in question. See attached image.
I named the storyboard being pushed because that is what is happening. Then in my storyboard named Push here is the setup.
In the first view controller of the tabbarcontroller I added the below code. Obviously this hides the navigation controller that pushed us here. If you then visit controller number 2 our new navigation controller and items show. If hiding the navigation controller in the tabbarcontroller view controller 1 is not what you want to do then. continue reading.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//or to unhide from returning the opposite ->self.parent?.navigationController?.isNavigationBarHidden = true
self.parent?.navigationController?.isNavigationBarHidden = true
}
If you did not want to hide the navigation controller in the first view controller but when visiting controller 2 you want to see your items then add this to your viewWillAppear and in the first controller in viewWillAppear change the code from true to false.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Do any additional setup after loading the view, typically from a nib.
self.parent?.navigationController?.isNavigationBarHidden = true
}
This hides the parent navigation controller as basically that was covering up your navigation controller in your example. So above hides the parent navigation controller. This is also why presenting modally worked. Your navigation controller was hidden from the start. Hope this helps.
**Edit
If you want the navigation controller in tab 2 view controller but you want to keep the parent in tab one to be able to go back with the back button you can set this in viewWillAppear instead so it would look like this in view controller 1.
//tabcontroller vc 1
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
And in tabcontroller view controller 2 with the item in the bar you could do this.
//tabbarcontroller vc 2 with own navigationcontroller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.parent?.navigationController?.isNavigationBarHidden = true
}
Finally if you want the back button visible in both controllers but want different right buttons do it programmatically in viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.setRightBarButton(UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(FirstViewController.editSomthing)), animated: true)
}
And if you want to remove it in the other controller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.rightBarButtonItem = nil;
}
In Both of the above examples directly above this, we are keeping the parent navigation controller so you would not need to embed your view controllers of the tab controller inside uinavigation controller.
You could also use a combo of the above code if you want the hide/show parent navigation controller in viewWillAppear as well. Some of this is dependent on the view hierarchy you choose now and in the future.

dismiss two controllers Swift

I have this situation :
I have a first view controller , when tap on button in it I open in modal mode another view controller , in this view controller when I tap another button I open in modal view another view controller and in it there is a button and when I tap on it I want to go to first view controller without re-initialize it.
How do I do it?
This is the perfect situation for an unwind segue.
Put this in your first viewController (the one you want to return to):
#IBAction func backFromVC3(_ segue: UIStoryboardSegue) {
print("We are back in VC1!")
}
Then in the Storyboard in your 3rd viewController, control-drag from your button to the exit icon at the top of the viewController and choose backFromVC3 from the pop-up.
Now, when the user presses the button in VC3, both VC3 and VC2 will be dismissed and you will return to VC1.
If you are not using Storyboards, you can dismiss the viewControllers with code. Here is code for a button's handler to dismiss two levels of viewController:
func doDismiss(_ sender: UIButton) {
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
Thanks all for reply and edited my question :)
I found 2 line code to resolved my problem:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil).
And that work well.
Thanks very much

Resources