I am facing a problem. When I want to change the View for a Tab View Controller, my application gives a black screen.
And here is my code to change view:
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
Constants.swift:
import Foundation
struct Constants {
struct Storyboard {
static let homeViewController = "homeVC"
}
}
homeVC is the first View of TabBarController, with the Label.
This is my way. I am not using storyboard by the way. I am using xib.
let dashboardVc = DashboardTabController()
self.window!.rootViewController = dashboardVc
self.window!.makeKeyAndVisible()
self.window?.overrideUserInterfaceStyle = .light
and then in dashboardTabController type this one.
import UIKit
class DashboardTabController: UITabBarController {
#IBOutlet weak var dashboardTabBar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
let firstViewController = HomeViewController()
firstViewController.tabBarItem = UITabBarItem(title: "", image: UIImage(named: "ic_home_24px"), selectedImage: UIImage(named: "ic_home_24px"))
let secondViewController = AddContactViewController()
secondViewController.tabBarItem = UITabBarItem(title: "", image: UIImage(named: "ic_group_add_24px"), selectedImage: UIImage(named: "ic_group_add_24px"))
let tabBarList = [firstViewController, secondViewController]
viewControllers = tabBarList
}
}
don't forget in DashBoardTabController xib, implement the UITabBar in bottom. Hopefully it's helpful. Just mention me if you need more help on executing this.
Related
click the link to view the image
There is something above the navigationbar, and I'm confused on what it is and how to get rid of it.
here is my tabController code
{import UIKit
class TabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
delegate = self
authenticateUserAndConfigureView()
}
func setupViewControllers() {
let home = templateNavController(viewController: DiscoverViewController(), image: UIImage(named: "house")!, title: "Home")
let search = templateNavController(viewController: SearchViewController(), image: UIImage(named: "search")!, title: "Discover")
let problem = templateNavController(viewController: NewProblemViewController(), image: UIImage(named:"addproblem")!, title: "Add New Problem")
let chat = templateNavController(viewController: MessageViewController(), image: UIImage(named: "chat")!, title: "Chat")
let profile = templateNavController(viewController: ProfileViewController(), image: UIImage(named: "profile")!, title: "Profile")
self.viewControllers = [home, search, problem, chat, profile]
}
func authenticateUserAndConfigureView() {
DispatchQueue.main.async {
if Auth.auth().currentUser == nil {
let navController = UINavigationController(rootViewController: LoggedOut())
navController.modalPresentationStyle = .fullScreen
self.present(navController, animated: true, completion: nil)
} else {
self.setupViewControllers()
}
}
}
func templateNavController(viewController: UIViewController, image: UIImage, title: String) -> UINavigationController {
let navController = UINavigationController(rootViewController: viewController)
navController.tabBarItem.image = image
navController.navigationBar.backgroundColor = .white
navController.tabBarItem.title = title
return navController
}
}
}
You can always use 'Debug View Hierarchy' xCode tool to see views hierarchy in a screen.
Just run the app on a simulator or device and click 'Debug View Hierarchy' when your screen is active.
Here you can rotate screen and see all active layers. Once you select a layer you can check it name and position in hierarchy on the left bar.
Hey Guys I figured it out! My mistake was that I cast my original TabBarController as a UINavigationController before setting the view controllers on there. Thus there was a navigation bar from the mistake UINavController and another navigation bar from the navigation controller that I cast on each view controller.
I have 3 view controllers in a UITabBarController. In only one view controller I would like to place it in a navigation controller. What is the proper way of doing this so that only one view controller has a Navigation Controller? I would like aController to be in a navigation controller.
import UIKit
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let mController = MViewController()
mpController.tabBarItem = UITabBarItem(title: "view1", image: UIImage(named: "viewoneimage"), tag: 0)
let inputController = InputViewController()
inputController.tabBarItem = UITabBarItem(title: "Input", image: UIImage(named: "plus"), tag: 1)
let aController = ATableViewController()
aController.tabBarItem = UITabBarItem(title: "custom", image: UIImage(named: "person.fill"), tag: 2)
let navController = UINavigationController()
// aController.navigationController = navController
viewControllers = [mController, inputController, aController, navController]
// Do any additional setup after loading the view.
}
}
You must embend your UIViewController inside the Navigation Controllers and initialize your tab menu with your Navigation Controllers.
Also for each tab you will have different Navigation Controller
Your code should look like that.
import UIKit
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let mController = MViewController()
mpController.tabBarItem = UITabBarItem(title: "view1", image: UIImage(named: "viewoneimage"), tag: 0)
let inputController = InputViewController()
inputController.tabBarItem = UITabBarItem(title: "Input", image: UIImage(named: "plus"), tag: 1)
let aController = ATableViewController()
aController.tabBarItem = UITabBarItem(title: "custom", image: UIImage(named: "person.fill"), tag: 2)
let navMController = UINavigationController(rootViewController: mpController)
let navInputController = UINavigationController(rootViewController: inputController)
let navaController = UINavigationController(rootViewController: aController)
viewControllers = [navMController, navInputController, navaController]
}
}
I have tabbar controller which done programmatically. And tab bar is working fine. In stroyboard, i have created firstViewController and assigned class name firstViewController. When i tried to tab on first vc on tab bar controller to navigates to first viewcontroller and it crash. if i give programmatically mean it works fine.
How to navigate from programmatically tab bar controller to storyboard view controller.
here is my code of tab bar controller:
let tabBarCnt = UITabBarController()
func createTabBarController() {
let firstVC = FViewController()
firstVC.tabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 0)
let secondVC = SViewController()
secondVC.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 1)
let thirdVC = ViewController()
thirdVC.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 2)
let fourthVC = ViewController()
fourthVC.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 3)
if UIDevice.current.userInterfaceIdiom == .pad {
let controllerArray = [firstVC, secondVC, thirdVC, fourthVC]
tabBarCnt.viewControllers = controllerArray.map{ UINavigationController.init(rootViewController: $0)}
self.view.addSubview(tabBarCnt.view)
} else {
let controllerArray = [firstVC, secondVC]
tabBarCnt.viewControllers = controllerArray.map{ UINavigationController.init(rootViewController: $0)}
self.view.addSubview(tabBarCnt.view)
}
}
Here is my firstVC of firstViewController code:
import UIKit
class FViewController: UIViewController, UITabBarDelegate {
#IBOutlet weak var firstBtn: UIButton!
#IBOutlet weak var fview: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
// self.fview.backgroundColor = .brown
// Do any additional setup after loading the view.
}
}
Please try below code. you can give view controller identifier by interface builder.
let tabBarCnt = UITabBarController()
func createTabBarController() {
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
let firstVC = storyboard?.instantiateViewControllerWithIdentifier("FViewController")
firstVC.tabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 0)
let secondVC = storyboard?.instantiateViewControllerWithIdentifier("SViewController")
secondVC.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 1)
let thirdVC = storyboard?.instantiateViewControllerWithIdentifier("ViewController")
thirdVC.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 2)
let fourthVC = storyboard?.instantiateViewControllerWithIdentifier("ViewController")
fourthVC.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 3)
var controllerArray = [firstVC, secondVC]
if UIDevice.current.userInterfaceIdiom == .pad {
controllerArray += [thirdVC, fourthVC]
}
tabBarCnt.viewControllers = controllerArray.map{ UINavigationController.init(rootViewController: $0)}
self.view.addSubview(tabBarCnt.view)
}
So programatically navigation controller is created and then assigned FirstVC or XVC as root for that navigation controller. This action has been repeated for all tabs.
So, in storyboard instead of dragging view controller you need to take navigation controller. I have attached screenshots.
Default it will give TableViewVC as root for Navigation controller
I'm trying to customize the title of my More button in my UITabBarController as I'm doing the app in another language. I subclassed UITabBarController to be able to access the tabBarController property. Unfortunately, it's always nil whether I put it in viewDidLoad or viewDidAppear(_). Any thoughts on how I can edit it?
import UIKit
class ControllerVC: UITabBarController {
let uiManager = UIManager()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
if let tabBarItem = tabBarController?.moreNavigationController.tabBarItem {
let deselectedImage = tabBarItem.image
let selectedImage = tabBarItem.selectedImage
tabBarController!.moreNavigationController.tabBarItem = UITabBarItem(title: "بیشتر", image: deselectedImage, selectedImage: selectedImage)
} else {
uiManager.showActivityIndicator(self)
}
}
}
The problem is not with moreNavigationController. The problem is with tabBarController. Your class is a UITabBarController. A tab bar controller's tabBarController property is always nil.
Just do:
let tabBarItem = moreNavigationController.tabBarItem
let deselectedImage = tabBarItem.image
let selectedImage = tabBarItem.selectedImage
moreNavigationController.tabBarItem = UITabBarItem(title: "بیشتر", image: deselectedImage, selectedImage: selectedImage)
I implemented SWRevealController with storyboard and everything works great, but now I would like to program the app without storyboard.
Can someone help me with the implementation? I have a FrontViewController and a MenuViewController. Do I need an extra SWRevealViewController for this and if yes, what do I have to code?
I know there is some information on SWRevealController but it is in Objective-C and I have some problems to write this in Swift 2.0.
You can do it as follow.
Create one function createSlidingMenu in appDelegate.
func createSlidingMenu(){
let frontViewController = //create instance of frontVC
let rearViewController = //create instance of rearVC(menuVC)
//create instance of swRevealVC based on front and rear VC
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC.toggleAnimationType = SWRevealToggleAnimationType.EaseOut;
swRevealVC.toggleAnimationDuration = 0.30;
//set swRevealVC as rootVC of windows
self.window?.rootViewController = swRevealVC!;
}
call createSlidingMenu in application:didFinishLaunchingWithOptions: and you are good to go.
This worked for me (in swift 3.1)
In the StoryBoard create MasterViewController, HomeViewController (embedded in UINavigationController) with storyboardId "HomeViewController", and MenuViewController (embedded in UINavigationController) with storyboardId "MenuViewController".
Create MasterViewController class and associate to UIViewController (MasterViewController) in Storyboard and implements SWRevealViewControllerDelegate protocol (see code)
import UIKit
class MasterViewController: UIViewController, SWRevealViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let frontNavigationController:UINavigationController
let rearNavigationController:UINavigationController
let revealController = SWRevealViewController()
var mainRevealController = SWRevealViewController()
let menuTable = self.storyboard?.instantiateViewController(withIdentifier: "MenuViewController")as! MenuViewController
let homepage = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
frontNavigationController = UINavigationController(rootViewController: homepage)
rearNavigationController = UINavigationController(rootViewController: menuTable)
rearNavigationController.setNavigationBarHidden(true, animated: false)
revealController.frontViewController = frontNavigationController
revealController.rearViewController = rearNavigationController
revealController.delegate = self
mainRevealController = revealController
UIApplication.shared.delegate!.window?.rootViewController = mainRevealController
}
}
As alternative you could omit MasterViewController and:
implement SWRevealViewControllerDelegate in AppDelegate and
copy the code of viewDidLoad body wrote above in application:didFinishLaunchingWithOptions:
In addition to Hitendra, I modify the following code so I can put navigation in Home
AppDelegate.swift
func toHome() {
let frontViewController = HomeController()//create instance of frontVC
let rearViewController = MenuController() //create instance of rearVC(menuVC)
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC?.toggleAnimationType = SWRevealToggleAnimationType.easeOut;
swRevealVC?.toggleAnimationDuration = 0.30;
navigationController = UINavigationController(rootViewController: swRevealVC!)
self.window?.rootViewController = navigationController
}
LoginController.swift, when user click login button
#objc private func login() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.toHome()
return
}
HomeController.swift
override func viewDidLoad() {
super.viewDidLoad()
setupLayout() // layout programmatically, I didn't put code here
let menuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self, action: #selector(HomeController.menu))
self.revealViewController().navigationItem.leftBarButtonItem = menuButton
}
#objc private func menu() {
revealViewController().revealToggle(self)
}