Load a Tabbarcontroller when button is clicked - ios

Im doing an application which is a tab bar controller app with tab bar items (Search, Login, More). After successful login of user tab bar changes to (Search, Account, More) with a Logout button in More. The problem is when Logout is clicked it should load SearchViewController and if again Login is clicked in tab bar the corresponding Login page doesn't show. It shows a black screen.
#IBAction func btnLogOutClicked(_ sender: UIButton)
{
let hm = SearchVC()
let tabOneBarItem = UITabBarItem(title: "Search", image: UIImage(named: "TabHome.png"), selectedImage: UIImage(named: "TabHome.png"))
hm.tabBarItem = tabOneBarItem
let lgn = LoginVC()
let tabOneBarItem1 = UITabBarItem(title: "Login", image: UIImage(named: "tabAcc.png"), selectedImage: UIImage(named: "tabAcc.png"))
lgn.tabBarItem = tabOneBarItem1
let mropt = MoreVC()
mropt.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 2)
let controllers = [hm, lgn, mropt]
self.tabBarController?.viewControllers = controllers
self.tabBarController?.selectedIndex = 0
}
How would I make a tab bar controller display when Logout is clicked and clicking the tab bar item should display corresponding view controller.

You have to load every vc like this after giving each one a storyboard identifier
let hm = storyBoard.instantiateViewController(withIdentifier: "SearchVC") as! SearchVC
This
let hm = SearchVC()
Is used when the vc is created programmatically , and it's the main reason for black screen as the vc is loaded without it's layout

There are some ways to load view of view controllers:
from nib files (use public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?))
from storyboards (use UIStoryboard to instantiate view controller)
load it directly (usually programmatically) by overriding loadView()
The default init method such as SearchVC() will call init(nibName: nil, bundle: nil) for you. What's going on in this case is here.
You have to use only first two option to load view from nib or storyboard correctly.
View Management is here to see more.

Related

How to open specific ViewController from TabBarController

Sorry, if it is an essential question.
The scheme is the following:
enter image description here
I want the following:
User taps last Tab
User goes to some ViewController (different from ViewController, actually connected with last Tab)
How to do this (without using segue)?
Thanks a lot in advance!
You can go with instantiateViewController with push when load your tab and push one viewController to another like below:
let next = self.storyboard?.instantiateViewController(withIdentifier: "nextVC")as! nextVC
self.navigationController?.pushViewController(next, animated: true)
You can assign ViewController in you UITabBarController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// create view controllers from storyboard
// Make sure you set Storyboard ID for both the viewcontrollers in
// Interface Builder -> Identitiy Inspector -> Storyboard ID
let clockViewController = storyboard.instantiateViewControllerWithIdentifier("ClockViewController")
let stopWatchViewController = storyboard.instantiateViewControllerWithIdentifier("StopWatchViewController")
// Set up the Tab Bar Controller to have two tabs
let tabBarController = UITabBarController()
tabBarController.viewControllers = [clockViewController, stopWatchViewController]
// Make the Tab Bar Controller the root view controller
window?.rootViewController = tabBarController

How to put tab bar in a seperate storyboard and not have problems with it and nav bar [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a lot of pages in my project so I am using multiple storyboaords. After my login page I want to go to a tab bar controller which has five pages. So my tab bar controller is in it's own storyboard. The storyboard name is HomePage and the tab bar identifier is HomePageVC.
So the code I'm using to call it from the login page (after logging in) is:
let storyboard = UIStoryboard(name: "HomePage", bundle: nil)
let secondVC = storyboard.instantiateViewController(identifier: "HomePageVC")
self.navigationController?.pushViewController(secondVC, animated: true)
The HomePage storyboard is then setup this way
[![enter image description here][1]][1]
Each of the five tabs lead to a different view controller in a different storyboard (I'm using storyboard references for this). Now I'm having three problems:
When I use this method to show the tab bar and the next view controller somehow there are two navigation controllers. So basically it's a view controller connected to a nav bar controller (and the nav bar controller is set as the initial view controller). The problem is the previous view controllers nav bar is being pushed to the next view controllers nav bar. Causing a double Mac bar. I want to remove the top nav bar and have the text of the below one.
The second problem I'm having is the tab bar doesn't actually show up properly it is just a gray bar. However, I think the buttons are still there as when I click on a section of the tab bar where a button should be, it goes to that view controller.
The last problem is that the images I put in for the tab bar buttons are too big. How do you resize them to be the proper size. I'm not sure if this is what is causing the second problem but it could be. So how could I solve these problems.
Note for the future: You should only ask one question at a time.
For question 1 - double navigation bar.
In your Login view controller, you can do this:
class LogInViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// show the navigation bar
self.navigationController?.setNavigationBarHidden(false, animated: false)
}
#IBAction func loginTapped(_ sender: Any) {
// hide the navigation bar
self.navigationController?.setNavigationBarHidden(true, animated: false)
let storyboard = UIStoryboard(name: "HomePage", bundle: nil)
let secondVC = storyboard.instantiateViewController(identifier: "HomePageVC")
self.navigationController?.pushViewController(secondVC, animated: true)
}
}
Question 2 - tab bar icons not showing.
Embedding a Tab Bar Controller in a Navigation Controller is generally considered bad practice, as navigation can be confusing for the user. However, I'm not Apple, and if it fits your design and the navigation remains intuitive...
I just gave it a try, and no, the tab bar button icons (and titles) don't show up. Not entirely sure why... but here is a way to do it.
First, delete all your current tab bar controller connections. So your "HomePage" Storyboard will simply have a Tab Bar Controller (with Storyboard ID of "HomePageVC").
Next, add a UITabBarController subclass to your project, and assign it to the "HomePageVC" tab bar controller. It will look something like this:
class MyTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
var sb = UIStoryboard(name: "Settings", bundle: nil)
guard let tab1VC = sb.instantiateInitialViewController() else {
fatalError("Could not load Settings VC!")
}
guard let tab1Icon = UIImage(named: "settignsTabIcon") else {
fatalError("Could not load settignsTabIcon image!")
}
tab1VC.tabBarItem = UITabBarItem(title: "Settings", image: tab1Icon, selectedImage: tab1Icon)
sb = UIStoryboard(name: "Communication", bundle: nil)
guard let tab2VC = sb.instantiateInitialViewController() else {
fatalError("Could not load Communication VC!")
}
guard let tab2Icon = UIImage(named: "communicationTabIcon") else {
fatalError("Could not load communicationTabIcon image!")
}
tab2VC.tabBarItem = UITabBarItem(title: "Comunication", image: tab2Icon, selectedImage: tab2Icon)
// etc for your other 3 tabs
let viewControllerList = [ tab1VC, tab2VC ]
viewControllers = viewControllerList
}
}
As to question 3 - tab icon size... you can probably find that with an easy search... if you can't, come back and ask that as a new post.

Swift and Xcode. All UIViewControllers become black when added to TabBarController

I'm trying to create UITabBarController programmatically, adding multiple NavigationControllers to it. When UITabBarController contains one NavigationController - everything works as expected (see image)
But when i add multiple NavigationControllers to UITabBarController each screen becomes black (see another image )
The same black screen is shown when switching between tabs 1, 2, 3, 4 and 5.
Here's the code how UITabBarController is created
class TabBarViewController : UITabBarController{
override func viewDidLoad() {
super.viewDidLoad()
let controllers = [HistoryViewController.self, StatsViewController.self, DashboardViewController.self, ExpenseManagerViewController.self, ProfileViewController.self]
var navControllers: [UINavigationController] = []
controllers.forEach{ ctrl in
navControllers.append(getController(from: ctrl))
}
tabBar.tintColor = Color.green
viewControllers = navControllers
}
private func getController<TType: UIViewController>(from type: TType.Type) -> UINavigationController{
let ctrl = TType()
let navCtrl = UINavigationController(rootViewController: ctrl)
let ctrlName = String.init(describing: type.self).replacingOccurrences(of: "ViewController", with: String.empty)
navCtrl.tabBarItem.title = ctrlName
navCtrl.tabBarItem.image = UIImage(named: ctrlName)
navCtrl.navigationBar.topItem?.title = ctrlName
return navCtrl
}
}
Those UIViewControllers are created using "add Cocoa Touch Class" option and have assigned *.xib files with some minimum design (see one more image)
Any help regarding why all screens become black when multiple (2 and more) NavigationControllers added to TabBarController would be highly appreciated.
Thanks
Clearly you forget how to init the UIViewControllers with xib file:
private func getController<TType: UIViewController>(from type: TType.Type) -> UINavigationController{
let ctrl = TType(nibName: String.init(describing: type.self), bundle: nil)
let navCtrl = UINavigationController(rootViewController: ctrl)
First if you come from any screen then dont insert navigationbar in between that viewcontroller and tabbarcontroller and when you jump to tabbarcontroller set as rootview controller and any tab you want to open than place navigation controller in between. means dont open tabbar controller with navigationbar heirarchy but when u want to open controller with tabs then place navigation controller in between.

How to have TabBarController at the bottom itself on selecting menu Item from the side menu?

I'm using SWRevealController to have a side menu. In my app ,it also have UITabBarcontroller.
My connection format is as SWRevealViewController--->UItabbarController--->NavigationController--->UITabbaritemPage-->Another vc
PLEASE CLICK ON THE IMAGE TO SEE IN CORRECT ORIENTATION
The above show is the layout I'm using.I want to have that burger button (menu button) in almost all vc that are showing from and in tabbarcontroller. Currently I'm getting the side menu when tapping on the Button (The image showed in right side as spereate).On choosing a menu, it shows the desired vc but,the bottom tab bar is not there. I want to have the bottom tabbar in entire pages also in pages from the side menu.
How can I acheive this? Please help me.
The code I'm using in didSelectRowAtIndexPath is:
if indexPath.row == 1{
let destinationVc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
let newFrontVc = UINavigationController.init(rootViewController:destinationVc!)
revealViewController.pushFrontViewController(newFrontVc, animated: true)
}
I think you don't actually need to push a view controller if using tab bar controller.
let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "TabBarController")
tabBarController.selectedIndex = 1
revealViewController.pushFrontViewController(tabBarController, animated: true)
You would have to set the identifier of the tab bar controller to be TabBarController in Main.storyboard for this to work.
I also had the same layout like you only few view controllers has been added to the tabbar and it will show the tab bar in all view controllers
SWRevealViewController with TabBarController using XIB in Swift 4
let objSideBarVC = SideBarVC(nibName: "SideBarVC", bundle: nil)
let navSidebar = UINavigationController(rootViewController: objSideBarVC)
navSidebar.navigationBar.isHidden = true
let objDashboardVC = DashboardVC(nibName: "DashboardVC", bundle: nil)
let navDashboard = UINavigationController(rootViewController: objDashboardVC)
navDashboard.navigationBar.isHidden = true
let mainRevealController = SWRevealViewController.init(rearViewController: navSidebar,frontViewController: navDashboard)
AppDelegate().window?.rootViewController = mainRevealController
mainRevealController.pushFrontViewController(TabBarController, animated: true)

Navigation and Tab View controllers don't load correctly, then jump into place

When I try to present a TabViewController, I get odd behavior from both my TabBar and NavigationBar as seen in the images below. It stays as shown in the "before" image until I touch the screen or push a button. At the point it jumps to the "after" image.
Before:
After:
Code used to present the TabViewController:
let delegate = UIApplication.shared.delegate as! AppDelegate
delegate.tabViewController = TabViewController()
self.present(delegate.tabViewController!, animated: true, completion: nil)
Initialization of the TabViewController:
override func viewDidLoad() {
super.viewDidLoad()
let groupTable = GroupTableViewController()
let nav = UINavigationController(rootViewController: groupTable)
nav.title = "Groups"
nav.tabBarItem.image = UIImage(named: "groups")
let vc2 = MeViewController()
vc2.title = "Me"
vc2.tabBarItem.image = UIImage(named: "user")
// let vc3 = SettingsViewController
// vc3.title = "Settings"
// vc3.tabBarItem.image = UIImage(named: "settings")
self.viewControllers = [nav, vc2]
self.selectedIndex = 0
}
Console log, but I don't think the error is relevant:
objc[63765]: Class PLBuildVersion is implemented in both /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11916f998) and /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x118069d38).
One of the two will be used. Which one is undefined.
This is a new bug I've been experiencing seemingly after updating to Xcode 8.1/MacOS Sierra.
My XCode version is Version 8.1 beta (8T47). Could this be a bug in the beta?
I'm unsure what is causing this as I didn't make a code change when this started happening.
Thanks for the help.
The viewDidLoad of the tab view controller is really too late to be configuring the tab view controller with its two child view controllers. Either do this in the "Code used to present the TabViewController", or, if you really want to do it from within the tab view controller itself, do it from the tab view controller's initializer. Then all will be well.

Resources