How to present view controller with Tab Bar - ios

My app starts off with a Tab Bar Controller on the first screen after logging in:
Later on the user can tap to get back to that screen, by pressing the Home button. The code for that is:
self.present(self.mealPlanViewController, animated: true, completion: nil)
The issue is that when they go back to that view controller, the Tab Bar is no longer there.
How can I present the view controller with the Tab Bar again?

You said:
"Later on the user can tap to get back to that screen, by pressing the Home button. The code for that is:"
self.present(self.mealPlanViewController, animated: true, completion: nil)
That is wrong. You are not "getting back" to anything. You are presenting self.mealPlanViewController modally. That means it is being drawn on top over everything else. If self.mealPlanViewController was previously on-screen, bad things may happen.
In order to help you sort it out, you need to explain your view controller hierarchy and the flow between screens. What is the name of your tab bar controller's class? Of the view controllers that are displayed as tabs? How are you getting from the tab bar controller to the screen that contains the home button?

I was able to figure it out - please see below:
I added #IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {} to the view controller I wanted to go back to. This added an Action Segue.
I added the segue to the storyboard and gave it the identifier, "unwindToMealPlanViewController"
I added the following code to my Done button: self.performSegue(withIdentifier: "unwindToMealPlanViewController", sender: nil)
These were some very helpful resources in solving this:
How to perform Unwind segue programmatically?
https://www.hackingwithswift.com/example-code/uikit/how-to-perform-a-segue-programmatically-using-performsegue
https://www.youtube.com/watch?v=ULd2v4mHyQ4

Related

Best segue after posting content

I am new to swift and I am curious about the best way to move from one view to another. I have a main view that is a tab on a tab bar and embedded in a navigation controller. From this main view, I am taking user content and then displaying that content on the main view. Currently I am segueing from the main view to a view that collects content and then another segue back to the main view. The only problem is that when I do this I get a back button and even if I hide the back button, I am just continuing to put screens on top of the tab. What would be the best way to transition from the view that collects content back to the main view?
Basically there're 2 general ways how view controllers are shown and hidden:
Push in the navigation controller (either with 'Show' segue or in code self.navigationController?.pushViewController(viewController, animated: true). In that case the normal way to return to previous screen would be to use 'Back' navigation button. If you need to do it manually you can use self.navigationController?.popViewController(animated: true) inside your view controller or use unwind segue (though I rarely see it used). If you need to come back to the very first screen in your navigation stack you can use self.navigationController?.popToRootViewController(animated: false).
Modal presentation (either with 'Present Modally' segue or with self.present(viewController, animated: false). In that case in order to return to the previous view you have to add some close/cancel button on your screen and bind it with the code which call self.dismiss(animated: true, completion: nil).
Anyway to have a full picture I'd recommend to get familiar with Apple guide on this subject.
And if you need to pass some data between your controllers, ther're various ways to do it, like assigning it directly to a property in prepare(for segue: UIStoryboardSegue, sender: Any?), implementing delegate/callback interactions, implementing observers, shared back storages, etc.

When segueing back to view controller in navigation controller, entire screen is blank

Right now, I have a view controller that is embedded within a navigation controller and that has a collectionView in it. When the user presses a button, I segue to another view controller which works fine, but when that user wants to go back to the original view controller, I have a segue but the original view controller simply shows up blank. Please help! I have attached my storyboard
You should exit segues for this purpose or else simply put the below line of code when you want to go back to previous view.
self.dismiss(animated: true, completion: nil)

Black screen appears on click of a button before navigation controller

I have a sign in page with 2 text fields for username, password and a button. Once you click on that button, it takes you to a view controller. There is a navigation controller in between that viewcontroller and the signincontroller.
For some reason, I get this black screen. Yesterday deleting a segue or a element on the storyboard would stop it from happening but now its consistently happening.
If I kill the running app, click on the app icon to load it again then it shows the signincontroller as expected. But initially this keeps happening.
I'm not sure what to do exactly.
I also tried to "Reset content and settings" and it still did not work.
My flow is:
SigninVC push-> NavigationController -> ViewController (no connection between navigationcontroller and viewcontroller as signinviewcontroller's button "signin" performs the segue:
self.performSegue(withIdentifier: "signin_success", sender: self)
[Update] Also please note I tried removing NavigationController completely and it does not give me that black screen anymore although there is now a white screen appearing before it loads the signinviewcontroller
Just add your navigation controller before every other controller and show navigation bar where you need and remove it where you do not need it.
If you can not make it please send me your test project and I will make it for you :)

How to unwind to the first view controller on a navigation stack

I have a problem with unwinding my view to login screen. The storyboard structure is as follow:
Storyboard Structure
The user flow for the app is as follow:
user login on LoginVC-> goes to main tab bar screen by modal segue-> on each tab bar item, I added right bar button on the navigation controller to access profile page, each tab bar item has independent navigation controller to keep the nav controller structure linear. -> once i click profile page button, profile page is presented modally -> when logout button on profile page is clicked, it triggers unwind segue and dismiss view controller
func logoutUser(){
//Networking.logoutUser()
print("It goes to login")
self.performSegue(withIdentifier: "unwindToLogin", sender: self)
}
The unwind segue was implemented on LoginVC on the leftmost VC.I connected unwind segue on the profile screen and call it "unwindToLogin"
I simply used performSegueWithIdentifier. However, the method does not get called and nothing happen to the view.
Edit 1:
Im wondering since i call profile page modally on tab bar vc, it couldnt find the unwindtologin.
If i simply use the instantiateviewcontoller to call login, will it clear my view controller stack ?
Edit 2:
Sorry, i forgot that when i check if a user is logged in, i use the code below:
if (FIRAuth.auth()?.currentUser != nil) {
self.storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
self.window?.rootViewController = self.storyboard?.instantiateViewController(withIdentifier: "TabBarViewController")
}
So actually they can't find the unwind method because the root view is not main login view controller.
Can anyone help ?
Move to any View controller using unwind segue.
For moves to any view controller when you clicking a button.
- (IBAction)unwindToCurrentController:(UIStoryboardSegue *)unwindSegue
{
}
Add these above lines to your loginViewController.m file (or) add
these lines to which view controller you want to move.
Actually you want to move to login view controller when clicking a
button. So,create a button or choose any button for this event.
Before doing this you want to add the above code to your login view
controller. Now add action to your button by dragging into Exit
option on view controller on the Top.
It shows an unwind option unwindToCurrentController.Click that option
and connect it.
Now Build and run your app. It works perfectly.
You need to create the unwind segue on every ViewController that you want to call it on. They can all use the same #IBAction destination in the login screen and they can all be called "unwindToLogin".
I see the unwind segue defined on the MainTabBarController. In your UserProfileController, you need to control-drag from the view Controller icon to the Exit icon and then select your #IBAction in the pop up. Then find that unwind segue in the UserProfileController in the Document Outline and make its identifier "unwindToLogin".
In response to your Edit 2:
Since your initial viewController was put into place programmatically, it isn't possible to unwind to the LoginViewController. In this case,
put the landing #IBAction in your MainTabBarController and have it set the self.window?.rootViewController to the login screen.
You could try this it Worked for me.
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
I use it to dismiss a modal view so that I can return to the originating view.

TabBar disappear after Push Segue

This is the current layout for my application. As you can see, I have a ViewController that is embedded in a TabBarViewController. You can see I have two tab bars in both of those bottom view controllers but only the first one shows up. In the second view controller after the push segue, the tab bar disappears. Why is this?
I added the properties for the First view controller and it is not set to hide the bottom bar during the segue so I am confused as to why it would disappear after the segue. Any ideas?
You'll need to wrap your tabBar's root viewControllers in a UINavigationController. So your UITabBarController would actually be pointed at the Navigation Controller. Then as you move around in that navigation controller, the tab bar will stay in place.
To fix this in your application, select your view controller in storyboard, then click "Editor" -> "Embed In" -> "Navigation Controller".
Here's a visual representation I just threw together for anyone else who comes across this problem. If you remove the "NavigationController" in the storyboard shown below, the tab will disappear when you click the button in "First View". With the navigation controller, you will maintain the tab bar. Hope this helps.
Try set self.tabBarController.tabBar.translucent = NO; in viewWillAppear
You could also try to dismiss the views by adding an outlet/action. For example, I experienced an issue where I had a TabBar view controller and needed to segue between 2 different views (ImageViews) on one of the tabs and as soon as I did a traditional segue, the whole tab bar disappeared. I had created the following "Back button" to clear the view:
#IBAction func backBtnPressed(_ sender: AnyObject) {
dismiss(animated: true, completion: nil)
}
Note: It is an important practice to clear views out as they will stack up overtime and will reduce the performance of your app.
Technical Info:
https://developer.apple.com/reference/uikit/uiviewcontroller/1621505-dismiss
Not sure if this helps but worth mentioning!

Resources