Swift - Overwrite navigation bar - swift

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) {
}

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))

Adding a UIBarButtonItem programmatically

I'm trying to add a UIBarButtonItem programmatically.
let navigation = UINavigationController()
let rightBarButton = UIBarButtonItem(title: "LogIn", style: .plain, target: self, action: #selector(logInPressed))
navigation.navigationItem.rightBarButtonItem = rightBarButton
And also made a selector function for testing.
#objc func logInPressed() {
print("go to login")
}
Unfortunately that does not work - bar button is not visible on navigation bar in simulator.
Checked with a breakpoint, rightBarButtonItem exists.
Probably issue can be caused by creating bar button from app coordinator, not from child VC.
Could please anyone help to troubleshoot this issue?
Simulator screenshot
you are adding UIBarButtonItem to a new instance of NavigationController. so it will not appear there.
so in your view controller which you want to handle right navigation bar , under one of these methods:
override func viewDidLoad()
or
override func viewWillAppear
add:
let rightBarButton = UIBarButtonItem(title: "LogIn", style: .plain, target: self, action: #selector(logInPressed))
self.navigationController?.navigationItem.setRightBarButton(rightBarButton, animated: true)
Issue was caused by creating bar button not from child VC, but coordinator.
Bar buttons are stored in navigationItem property of UIViewController.

Using UINavigationItem on UITabBarController

I have a project with a UITabBarController and a couple of views. Sort of like this:
In this project, the tab bar controller is called by tapping the Tab button on the UIViewController. I would like to get rid of the back button with "Title", and replace it with an "X" icon. When tapped, the "X" icon would dismiss the UITabBarController and return to the caller. I do this all of the time on UINavigationController using a UINavigationItem, but that does not appear to work in this situation. I drag the UINavigationItem to the view and it allows it, but it does not show up on the view and any UIBarButtonItem that I drag and drop on it do not appear.
Is there a way to actually do this? I'd even be ok with leaving the existing back button as it is and just getting rid of "Title"
I figured it out right after posting the question. Just a bit more research is all it took.
To fix this, add the following to the UITabBarController code.
override func viewDidLoad() {
super.viewDidLoad()
let buttonImage = UIImage(named: "back")
let leftButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(dismissTabBar))
leftButton.tintColor = UIColor.black
self.navigationItem.leftBarButtonItem = leftButton
}
#IBAction func dismissTabBar() {
self.navigationController?.popToRootViewController(animated: true)
}
This gives me a black back button with my image. When I tap it, it brings me back to the calling 'UIViewController.

Left Bar Button Item - show name of previous View Controller

If you have a Navigation Controller with no Bar Button Items, a navigation back button will be shown with the name of the last View Controller.
I want to keep that name, as in I don't want to have to hardcode it. I do know how to add it in but I don't want to have to do that because that leaves more room for bugs.
Is there a way that I can have a left Bar Button Item and for the default one to not go away?
Add this in viewController where you want to have default back button and custom bar button item. You can customise the bar button item.
override func viewDidLoad() {
super.viewDidLoad()
let newBtn = UIBarButtonItem(title: "new", style: .plain, target: self, action: #selector(anotherMethod))
self.navigationItem.leftItemsSupplementBackButton = true
self.navigationItem.leftBarButtonItem = newBtn//self.navigationItem.leftBarButtonItems = [newBtn,anotherBtn]
}

Programmatically create a navigation view

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!