Programmatically create a navigation view - swift

So I'm trying to create an app but I'm trying to avoid the use of storyboards. Hence just using swift files along with XIB files.
I have worked a little with Navigation controllers before but not enough I guess. So far I have this:
In AppDelegate I have:
let homeVC = HomeViewController()
let rootVC = UINavigationController(rootViewController: homeVC)
window!.rootViewController = rootVC
window!.makeKeyAndVisible()
My view currently is entirely empty, but with the basic "View" screen that comes with creating a new XIB file. I've set the size of that to freeform, and all other things like Top Bar, Status Bar are Inferred.
In my HomeViewController.swift I have:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let nib = UINib(nibName: "HomeView", bundle: nil)
let objects = nib.instantiateWithOwner(self, options: nil)
self.view = objects[0] as! UIView;
print(self.navigationController)
// customize navigation bar
let settingsImage = UIImage(named: "settingsWheelBlack.png")
let settingsNavItem = UIBarButtonItem(image: settingsImage, style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("selector"))
let addStuffItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: nil, action: Selector("selector"))
self.navigationController?.navigationItem.title = "Home"
self.navigationController?.navigationItem.leftBarButtonItem = settingsNavItem
self.navigationController?.navigationItem.rightBarButtonItem = addStuffItem
print(self.navigationController?.navigationBar)
print(self.navigationController?.navigationItem.title)
}
But when I run the application the navigation bar doesn't show up. Here's what I've tried besides what I currently have:
Add a Navigation Bar control to my XIB and connect an IB outlet to it. Also connect the IB outlet to the navigation item that already exists in the navigation bar control. Then set the title, and left and right buttons in that. Didn't work
Set the title and buttons in AppDelegate straight away for the rootVC defined above. Didn't work.
Any ideas what I'm missing?

I solved this after gathering some strength to read through tons of Apple docs. On this page I found this small piece of text:
In a navigation interface, each content view controller in the navigation stack provides a navigation item as the value of its **navigationItem** property. The navigation stack and the navigation item stack are always parallel: for each content view controller on the navigation stack, its navigation item is in the same position in the navigation item stack.
So I left my AppDelegate code as is and changed me viewDidLoad function to:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let nib = UINib(nibName: "EventsHomeView", bundle: nil)
let objects = nib.instantiateWithOwner(self, options: nil)
self.view = objects[0] as! UIView;
print(self.navigationController)
// customize navigation bar
let settingsImage = UIImage(named: "settingsWheelBlack.png")
let settingsNavItem = UIBarButtonItem(image: settingsImage, style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("selector"))
let addStuffItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: nil, action: Selector("selector"))
// Each VC within a navigation controller has it's own navigationItem property that the underlying navigation controller uses to show in the navigationBar
self.navigationItem.title = "Home"
self.navigationItem.leftBarButtonItem = settingsNavItem
self.navigationItem.rightBarButtonItem = addStuffItem
}
And viola!

Related

Navigation Controller inside Tab Bar Controller is showing but Right Bar Button not showing - Swift 4 - Programmatic Approach

I'm still new to iOS Dev.
Goal: Create an iOS App with Navigation Bar (with .add as right bar button) at the top and Tab Bar at the bottom screen using Programmatic approach (not using storyboards and xib)
So I did almost everything here: https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/CombiningViewControllers.html
But apparently it doesn't work (maybe because it is old? idk) and I'm also not comfortable configuring the App Delegate yet.
So what I have are these:
CompanyViewController as UIViewController
AssessmentViewController as UIViewController
TabViewController as UITabBarController, UITabBarControllerDelegate
I tried putting navigation controllers inside each VCs (navigationBar when I tap Tab Bar Items, which is expected - but the Title and Right Bar Button is NOT showing
I tried creating Swift file UINavigationController and named it NavigationViewController then added it to the TabViewController -> viewControllers but what happened was it was added to the tab bars at the bottom of the screen so it's not what I need and it looks like an ordinary tab not a navigation bar.
This is the last one I tried which displays Navigation Controller with its title but not its right bar button...
class TabViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let tabOne = CompanyViewController()
let tabOneBarItem = UITabBarItem(title: "Company", image: .none, tag: 1)
tabOne.tabBarItem = tabOneBarItem
let tabTwo = AssessmentViewController()
let tabTwoBarItem2 = UITabBarItem(title: "Assessment", image: .none, tag: 2)
tabTwo.tabBarItem = tabTwoBarItem2
self.viewControllers = [tabOne, tabTwo]
setUpNavigation()
}
func setUpNavigation() {
navigationItem.title = "Company Assessmentz"
self.navigationController?.navigationBar.barTintColor = colorLiteral
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:colorLiteral]
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(selectorX))
}
#objc func selectorX() { }}
replaced this:
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(selectorX))
to this:
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(selectorX))

How can I hide/show my toolbar item when a button is selected/deselected?

I made a navigation bar with three buttons - Plans,Visit and Documents and every time a button is selected/clicked a view is added as a child into a container view (Code for the other buttons are similar)
#IBAction func planAction(_ sender: UIButton) {
let newPlan = sender.frame.origin.x
scrollView.subviews.forEach{$0.removeFromSuperview()}
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let nextController = storyBoard.instantiateViewController(withIdentifier: "PlansViewController2") as! PlansViewController2
addChildView(viewController: nextController, in: scrollView)
self.movingView.frame.origin.x = newPlan
}
Now I want to add a tool bar item that only shows up when Plans or Documents is selected and disappears when Visit is selected.
At the moment I add my tool bar item in the viewDidLoad method:
self.toolbarItems = [UIBarButtonItem(title: "Kategorienliste", style: .plain, target: self, action: #selector(handleCategoryListTap(sender:)))]
How can I add a toolbarItem when a certain button is selected and remove it when another button is selected? Thanks in advance!
You can create your UIBarButtonItem with a custom view like:
let button = UIButton()
let barButtonItem = UIBarButtonItem(customView: button)
self.toolbarItems = [barButtonItem]
to hide / show you can access the button as the following:
let barButtonItem = self.toolbarItems.first
barButtonItem.customView?.isHidden = true
Hope it helps.

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.

UIBarButtonItems created programatically with Swift, not visible

I'm not sure why this piece of code which is supposed to embed two bar button items in a navigation controller's toolbar won't work. The toolbar itself is visible when I run my code, but not the bar button items. What am I doing wrong here? Thanks for attention.
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
//Tool bar appearance
toolbar.barTintColor = UIColor.blackColor()
//Show tool bar by default
self.navigationController?.toolbarHidden = false
//Icons all located in images.xcassets
let homeImage = UIImage(named: "home")
let gameImage = UIImage(named: "logo")
var toolBarItems = [UIBarButtonItem]()
let homeButton = UIBarButtonItem(image: homeImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(NavigationController.toHome))
homeButton.title = "Home"
let gameButton = UIBarButtonItem(image: gameImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(NavigationController.toGame))
homeButton.title = "Game"
//Place the bar items in toolBarItems array
toolBarItems.append(homeButton)
toolBarItems.append(gameButton)
//self.toolbar.items = toolBarItems
self.toolbar.setItems(toolBarItems, animated: true)
}//End viewDidLoad
func toHome() {
let homeVC = HomeViewController(nibName: "HomeViewController", bundle: nil)
self.pushViewController(homeVC, animated: true)
}
func toGame() {
let gameVC = GameViewController(nibName: "GameViewController", bundle: nil)
self.pushViewController(gameVC, animated: true)
}
}
Did you create a second .swift file for your dependent controller? You should move this code to the dependant controller file
self.navigationController?.toolbarHidden = false
let button1 = UIBarButtonItem(title: "home", style: .Plain, target: self, action: #selector(SecondViewController.home))
let myToolBar = [button1]
self.setToolbarItems(myToolBar, animated: true)
I am not sure but I think your buttons has size 0. So maybe you should add some constraints or view frame size. You can try debugging using the view hierarchy debugger.
Maybe you just have to replace this self.navigationController?.toolbarHidden = false
With this toolbarHidden = false
I'm confused by your code. Is the class you show us, the one Navigation Controller where all other ViewController depend on or is it itself one dependent ViewController that in this case appears to be a Navigation Controller? Or is it a Navigation Controller by mistake? (not very likely)
Why I ask? At one time you're referring to the parent navigation controller with self.navigationController?.toolbarHidden = false which is not this navigation controller itself. Then in the rest of the code, you refer to this controller itself.
Hope this leads to the right thinking.

Swift - Overwrite navigation bar

When it comes to opening a new View Controller i didnt want it to be presented modally so i pushed it in navigation controller:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("newView")
self.navigationController!.pushViewController(vc, animated: true)
The View with the identifier "newView" is presented correctly and there is also a navigation bar with a back-button provided, which also works properly.
But how to customize this existing navigation bar, add new bar button items etc.. ?
any suggestions?
Thanks and Greetings!
You are on the right track by subclassing from UIViewController the newView. I doubt you could customize the navigation bar on the storyboard.
You have to do it in code.
In viewDidLoad() of newView, you can have these:
var helloButton = UIBarButtonItem(title: "Hello", style: .Plain, target: self, action: "sayHello:")
self.navigationItem.rightBarButtonItem = helloButton
Implement the sayHello method:
func sayHello(sender: UIBarButtonItem) {
}