I am trying to implement bottom navigation bar for my iOS application. However, when I am creating tabBarItem, it is not showing on TabBar. TabBar is displaying correctly. I cannot figure out where is the problem, any help will be very appreciated.
If any additional information is required, please give me a sign. My code (simplified):
AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = TabBarController()
return true
}
}
TabBarController:
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let homeController = HomeController()
let navigationController = UINavigationController(rootViewController: homeController)
navigationController.title = "Home"
navigationController.tabBarItem.image = UIImage(named: "icon")
viewControllers = [homeController]
}
}
HomeController:
class HomeController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.tabBar.isHidden = false
}
}
EDIT:
I removed not crucial parts of the code, like isLoggedIn() function call, mentioned in the comments and changed MainNavigationController to TabBarController.
According to Matts answer I also changed this line in a TabBarController (but still bar item is not showing for some reason):
viewControllers = [navigationController]
The problem is this line:
viewControllers = [homeController]
homeController is not navigationController. So what happened to navigationController? Nothing. It vanished in a puff of smoke. You created navigationController but then you threw it away.
So nothing you say about navigationController and its configuration (including its tab bar item) has any effect; it is not in the interface (or anywhere else).
This is my complete test code (based on your code):
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = MainNavigationController()
return true
}
}
class MainNavigationController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let homeController = HomeController()
let navigationController = UINavigationController(rootViewController: homeController)
navigationController.tabBarItem.title = "MyCoolTitle"
viewControllers = [navigationController] // not [homeController]
}
}
class HomeController: UIViewController {
}
Related
I am trying to make a UITabBarController and a UINavigationController programmatically. I've tried many tutorials but most use Swift 3 which is too outdated and doesn't work.
AppDelegate.swift Snippet:
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalTableViewController()
let navController = UINavigationController(rootViewController: journalVC)
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
JournalTableViewController.swift Snippet:
var tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt = UITabBarController()
tabBarCnt.tabBar.barStyle = .black
let journalVC = JournalTableViewController()
journalVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarCnt.viewControllers = [journalVC]
self.view.addSubview(tabBarCnt.view)
}
What works:
The build loads onto the simulator
What doesn't work:
The build crashes once loading onto the simulator
After crashing, the error Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee6c2ada8) apears over this line 12 of JournalTableViewController.swift Snippet
If you are going to combine a UITabBarController and a UINavigationController then you will want the tab bar controller to be the root view controller. Each tab can have its own navigation controller if required.
If you make the navigation controller the root, then as soon as you push a new view controller, the tab bar will disappear. By making the tab bar the root, you can have a series of navigation hierarchies and switch quickly between them using the tab buttons.
AppDelegate.swift
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalViewController()
let navController = UINavigationController(rootViewController: journalVC)
let tabBarController = UITabBarController()
navController.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarController.viewControllers = [navController]
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
return true
}
There is no need for any specific code in your view controller class.
JournalTableViewController.swift Snippet:
override func viewDidLoad() {
super.viewDidLoad()
}
I think there is a typo in your snippet. In the following code, we added an intermediate vc to solve recursive problems.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalViewController()
let navController = UINavigationController(rootViewController: journalVC)
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
Here is journal vc:
class JournalViewController: UIViewController{
var tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt = UITabBarController()
tabBarCnt.tabBar.barStyle = .black
let journalVC = JournalTableViewController()
journalVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarCnt.viewControllers = [journalVC]
self.view.addSubview(tabBarCnt.view)
}
}
while the tableviewcontroller should be like this:
class JournalTableViewController: UITableViewController{
}
When I try to add a custom UINavigationBar to a view controller like this
class ViewController: UIViewController
{
static let nav_bar_height: CGFloat = 64
let nav_bar: UINavigationBar =
{
let nav_bar = UINavigationBar()
nav_bar.translatesAutoresizingMaskIntoConstraints = false
nav_bar.backgroundColor = .blue
return nav_bar
}()
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = .yellow
view.addSubview(nav_bar)
nav_bar.heightAnchor.constraint(equalToConstant: ViewController.nav_bar_height).isActive = true
nav_bar.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
nav_bar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
nav_bar.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
}
}
two distinct bars show up.
Any idea on why there is the white colored bar with a smaller height?
This is the AppDelegate
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let vc = ViewController()
window?.rootViewController = vc
// Override point for customization after application launch.
return true
}...
You're probably in navigation interface with a UINavigationController as your view controller's parent.
So the second navigation bar is the UINavigationController's navigation bar.
With a very basic single view application, I've deleted the main storyboard file and removed any references to it. As such I'm setting the window rootViewController programmatically. However, while this displays the single view (containing a label) correctly in simulator, it displays a black screen when running it on device. Here is the only code for the app.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = DummyViewController()
window?.makeKeyAndVisible()
return true
}
I've removed the entry for Main storyboard from the info.plist file, as well as the 'Main Interface' entry in the General settings.
I'm using Swift 3 and targeting an iOS 8 device. I'm using XCode 8.3.1.
There is no output in the console, and there are no exceptions. The viewDidLoad function is even triggering on breakpoint, so the codepath seems to be running correctly.
Any ideas?
Here's the bare bones code for DummyViewController upon request.
class DummyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
General settings showing no reference to Main Interface
Here is the image for the .xib linked to DummyViewController
** The solution to get around this case is to manually specify the .xib to load for the DummyViewController **
It looks like the ViewController is not set to display anything. Unless you are using a xib (in which case you would need to load the view controller in a different way, see below), there is nothing describing how the ViewController's view should render.
To test this out, you can add the line self.view.backgroundColor = UIColor.red to the ViewController's viewDidLoad() method, then run it again on the device- if the background color turns red, then hooray! The next step will be programmatically adding a UILabel.
Loading UIViewController From a XIB
let vc = MyViewController(nibName: "xibname", bundle: nil)
Alternatively, you can mask the loading by adding a custom init inside MyViewController:
class MyViewController: UIViewController {
required init() {
super.init(nibName: "xibname", bundle: nil)
}
}
(Thank you zonily-jame for the addition of hiding it in the class)
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let loginView : BaseClassVC = mainStoryboardIpad.instantiateViewControllerWithIdentifier("BaseClassVC") as BaseClassVC
let navigationController = UINavigationController(rootViewController: loginView)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
change Your window root as and set color
let viewController:DummyViewController = DummyViewController()
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = viewController
And change your controller
override func viewDidLoad() {
self.view.backgroundColor = UIColor.white
}
You just need to initialize viewcontroller object and implement white background color to its instance.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
//Add below 2 lines
let vc = DummyViewController()
vc.view.backgroundColor = .white
window?.rootViewController = vc
window?.makeKeyAndVisible()
return true
}
So as per title, I'm trying to present a UITableViewController from a UITabBarController. If you look at the video I've attached, on the third tab, it presents a view controller modally. Which is what I want to achieve.
https://vid.me/B0oy
I've been searching all day for a solution, and I yet I've tried them, but it doesn't work.
This is currently how I do it. I add this line of code in the view controller of my first tab.
self.tabBarController?.delegate = UIApplication.sharedApplication().delegate as? UITabBarControllerDelegate
And this is inside my AppDelegate.
class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegate {
var window: UIWindow?
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
if viewController is YourViewController {
if let newVC = tabBarController.storyboard?.instantiateViewControllerWithIdentifier("YourVCStoryboardIdentifier") {
tabBarController.presentViewController(newVC, animated: true, completion: nil)
return false
}
}
return true
}
func setStatusBarBackgroundColor(color: UIColor) {
guard let statusBar = UIApplication.sharedApplication().valueForKey("statusBarWindow")?.valueForKey("statusBar") as? UIView else {
return
}
statusBar.backgroundColor = color
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
setStatusBarBackgroundColor(UIColor.lightGrayColor())
return true
}
I have a ViewController called MyViewController and I want to load it programmatically without a stroyboard or xib.
As a follow up squestion, I would like to load a MyTableViewController inside a navigation controller. Again, I need to do it programmatically without using Storyboard or xib.
Please help.
I was able to solve my issue by removing the Storyboard and using the following code in AppDelegate
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// Override point for customization after application launch.
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
let myViewController: MyViewViewController? = MyViewViewController()
self.navigationController = UINavigationController(rootViewController: myViewController!)
self.window!.rootViewController = self.navigationController
return true
}
...
}