Login screen to UITabBarController missing navigation links - swift

My login screen is embedded in a Navigation Controller.
Once user logs in with correct credentials, I want to push the user to the UITabBarController. I am able to do this, but when I go to different views by clicking on the tabs, then the individual views don't have any navigation buttons appearing.
In app delegate, once login is successful I am using the following code:
let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main", bundle:nil)
let protectedPage = myStoryBoard.instantiateViewController(withIdentifier: "MainView") as! UITabBarController
let protectedPageNav = UINavigationController(rootViewController: protectedPage)
self.window?.rootViewController = protectedPageNav
How can I solve this?

As per Apple documentation states you should preferably assign UITabBarController as root of UIWindow.
So change your code.
let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main", bundle:nil)
let protectedPage = myStoryBoard.instantiateViewController(withIdentifier: "MainView") as! UITabBarController
//change UIViewAnimationOptions enum value and you will get some animation
UIView.transition(with: self.window!, duration: 0.34, options: UIViewAnimationOptions.transitionCrossDissolve, animations: {
self.window?.rootViewController = protectedPage
}, completion: {competion in
})

Related

How to set UINavigationController as root from UITabBarController.?

I am working on App where Login is shown to user, after successful login user is landed on dashboard. where 4 tabs are shown to navigate to respective use.
I have to use, UITabBarController for four tabs from dashboard and UINavigationController for navigation from LoginView.
I set my UITabBarController to navigationController, when user successfully logged in.
Each view will have one logout button, on click of which I have to set my navigationcontroller back to root.
Here is code sample which I have done.
My UITabBarController
class TabBarVC: UITabBarController {
let dashboardViewObj = DashboardVC()
let registerViewObj = RegisterVC()
let alertViewObj = AlertVC()
let historyViewObj = HistoryVC()
override func viewDidLoad() {
super.viewDidLoad()
self.viewControllers = [dashboardViewObj, registerViewObj,historyViewObj,alertViewObj]
// Do any additional setup after loading the view.
dashboardViewObj.tabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 0)
registerViewObj.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 0)
historyViewObj.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 0)
alertViewObj.tabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 0)
}
In my LoginViewContoller
let tabbarObj = TabBarVC()
#IBAction func loginBtnClicked(_ sender: Any) {
self.navigationController?.setViewControllers([tabbarObj], animated: true)
}
Now on click of logout button from any of these views, I need to set navigationController as root.
How to do it...?
Following chart will help to understand what I need.
Any help will be appeciated.
#frzi :- Thank you very much for answers and correction from comment section.
I just did what you suggested.
The following line is corrected in my LoginViewController.
self.navigationController?.setViewControllers([tabbarObj], animated: true)
To updated line as
self.navigationController?.pushViewController(tabbarObj, animated: true)
And on Logout button action just added the line,
self.tabBarController?.navigationController?.popViewController(animated: true)
and it worked...
Cheers J...
You can use unwind segue easily instead of setting the root view controller or pop view controller or even dismiss methods!
See this for full description
When you are login all you need to put this code in your logout button action and it will redirect you to login page.
var window: UIWindow?
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let VC = self.appDelegate.storyboard1.instantiateViewController(withIdentifier: "Your controller name") as! loginViewController
self.appDelegate.navigationController = UINavigationController(rootViewController: VC)
self.appDelegate.navigationController?.navigationBar.isHidden = true
self.appDelegate.window?.rootViewController = self.appDelegate.navigationController
self.appDelegate.window?.makeKeyAndVisible()
it will work.

TabBar controls the NavigationBar

I added 2 ViewControllers into a TabBar, but now, the TabBar's NavigationBar 'took over' each view's NavigationBar.
I can't set a title for each one of them, I can't add buttons, nothing.
I tried a few solutions to solve it that I found on the internet, but nothing worked.
I need control over the NavigationBar of each one of the views, as I need them to be different, with different title, etc.
This is my TabBar code:
class TabBar: UITabBarController {
let homeVC = HomeVC()
let followingVC = FollowingVC()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.appColors.mainWhite]
navigationController?.navigationBar.tintColor = UIColor.appColors.mainWhite
navigationItem.setHidesBackButton(true, animated: false)
homeVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 0)
followingVC.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let tabBarList = [homeVC, followingVC]
viewControllers = tabBarList
}
}
I really need the option to configure each NavigationBar from it's own ViewController, or atleast from the TabBar class.
You should add UINavigationController to each of your ViewControllers not your UITabBarController
First remove the UINavigationController of your TabBar, Either you have done this pragmatically or in the storyboard remove that first.
Second add UINavigationController to you ViewControllers
class TabBar: UITabBarController {
let homeVC = HomeVC()
let followingVC = FollowingVC()
override func viewDidLoad() {
super.viewDidLoad()
homeVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 0)
followingVC.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let homeNavigationController = UINavigationController(rootViewController: homeVC)
let followingNavigationController = UINavigationController(rootViewController: followingVC)
let tabBarList = [homeNavigationController, followingNavigationController]
viewControllers = tabBarList
}
}
Now if you change any properties like title and barButtons it will reflect accordingly.
Figured it out, the solution is:
The NavigationBar was not the TabBar navigation bar, but the screen that lead to the TabBar (Login Screen for example), I fixed it by hidding the navigation bar of the login screen when transfering to the TabBar controller, now the navigation bar of each view controller is shown and not blocked by the Login Viewcontrolelr navigationbar.

Present viewcontroller with tabbar

I created UITabBarController programmatically in AppDelegate with 4 view controllers(using .xib). When user tap some button on ViewController (VC-A) it present another VC (VC-B) and covered tabbar. So I want to VC-B has a tabbar on the button.
I tried to add VC-B as a child of tabbarcontroller. I tried to .present(vc) and .show(vc) on both: VC-A and VC-A.TabBarController
Creating controllers in AppDelegate:
let controllers = [tabViewController1,tabViewController2,tabViewController3,tabViewController4]
tabBarController.viewControllers = controllers
window?.rootViewController = tabBarController
presenting in VC-A
self.tabBarController?.present(controller, animated: false, completion: nil)
right click and drag from tabbar controller in storyboard to VC-B. that should create a tab on the bottom of your VC-A and VC-B to go back and forth without having to implement any backend code unless you want to animate
The solution is to embed every VC in navigationController and then add to TabBarController.
let vc1 = ViewController1()
let navController1 = UINavigationController(rootViewController: vc1)
navController.isNavigationBarHidden = true
let controllers = [navController1, navController2, navController3, navController4]
tabBarController.viewControllers = controllers
window?.rootViewController = tabBarController
Then call
self.navigationController?.pushViewController(controller, animated:
true)
To diplay VC with tabbar
I will press the red login button at the bottom of the picture and try to log in.
login button => "로그인"
After that, log in.
let moreVC = self.storyboard?.instantiateViewController(withIdentifier: "MoreViewController") as! MoreViewController
moreVC.definesPresentationContext = true
moreVC.modalPresentationStyle = .fullScreen
let navController = UINavigationController(rootViewController: moreVC)
self.present(navController, animated: true, completion: nil)
If the login proceeds without error, the above code will be called to display the screen when the login is completed.
If the flow proceeds as the code above, this screen appears.
The screen shown is not fullscreen, and the tabbar at the bottom is gone. The screen I want is the screen below.
How can I present a tab bar when presenting the screen?

How to make transparent to second View controller using Swift

I have really trouble to make transparent a view controller. I have 2 view controller. and trying to make transparent second view controller.
This is my first view controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destViewController : SearchViewController = storyboard.instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController
destViewController.getSearchTxt = self.tagsData[indexPath.row]
// destViewController.modalPresentationStyle = .currentContext
destViewController.modalPresentationStyle = .overCurrentContext
self.navigationController!.pushViewController(destViewController, animated: true)
this is my second view controller.
self.view.isOpaque = false
self.view.backgroundColor = .clear
black background is displaying instead of trasparent
For UINavigationController displaying .overCurrentContext is impossible. If you want to display it overCurrentContext use present
self.present(destViewController, animated: true)
If pushViewController is really required you can try to save the previous view to image and add it as a subview to the new SearchViewController.view.

Can it be non rootviewcontroller?

I'm implementing a drawer layout design in an app.
But my app starts with a small screen with an animated logo (simple HTML5 animation), then a login screen (g+ and Facebook), then the main screen where I'm implementing the MMDrawerController.
The question is in my AppDelegate:
window?.rootViewController = centerContainer
window?.makeKeyAndVisible()
So the app start in this screen. Is it possible to not make rootviewcontroller the center container and still using MMDrawerController?
I need to add MMDrawerController to my third viewcontroller in my app
But, in order to MMDrawerController to work, it requires to be the rootViewController
I allready tried to add to my first ViewController an Empty MMDrawerLayout but, then, the third controller no longer works
//global var
var centerContainer : MMDrawerController?
// then the appdelegate
let rootViewController = self.window!.rootViewController
let mainStoryBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let centerViewController = mainStoryBoard.instantiateViewControllerWithIdentifier("GaleriaPeliculas")
let leftViewController = mainStoryBoard.instantiateViewControllerWithIdentifier("LeftSideViewController")
let leftSideNav = UINavigationController(rootViewController: leftViewController)
let centerSideNav = UINavigationController(rootViewController: centerViewController)
//And here is the problem,
window?.rootViewController = centerContainer //how can it work without this line??
window?.makeKeyAndVisible()
Is it possible to not make rootviewcontroller the center container and still using MMDrawerController?
No. You need to keep MMDrawerController as the rootViewController if you still want to make use of the left/right drawers. It's no different than a UITabBarController in the sense that it contains multiple view controllers to be conditionally displayed.