set navigationBar background image in swift - uinavigationbar

Code below is not working for me, can anyone help to figure it out what is wrong?
var image = UIImage(named: "10384605_10152519403846670_5189785375955620548_n.jpg") as UIImage
self.navigationController.navigationBar.setBackgroundImage(image , forBarMetrics:UIBarMetrics)

self.navigationController.navigationBar.setBackgroundImage(image,
forBarMetrics: .Default)

In AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Image Background Navigation Bar
let navBackgroundImage:UIImage! = UIImage(named: "backgroundNB.png")
UINavigationBar.appearance().setBackgroundImage(navBackgroundImage, forBarMetrics: .Default)
return true
}

In Swift 3:
If you want to add a repeating image in the background you can make this call in AppDelegate > didFinishLaunchingWithOptions:
let image = UIImage(named: "imageNameInAsset")
UINavigationBar.appearance().setBackgroundImage(image, for: .default)
If you want to add an image to the center of the navigation bar you need to do this in the ViewController > viewWillAppear:
let titleView = UIImageView(image: UIImage(named: "imageNameInAsset"))
self.navigationItem.titleView = titleView

If you want to fill the image in navigation bar just use the code:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "your_Background_Image_Name")?.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch), for: .default)

let navBackgroundImage:UIImage! = UIImage(named: "navbar_bg")
[UINavigationBar .appearance().setBackgroundImage(navBackgroundImage, forBarMetrics:.Default)]

For Swift 3:
In AppDelegate.swift:
UINavigationBar.appearance().setBackgroundImage(UIImage(named:"pattern.png"),
for: .default)
OR
In viewDidLoad():
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named:"pattern.png"),
for: .default)

set backgroundImage in Navigation controller
self.navigationController?.navigationBar .setBackgroundImage(UIImage(named: "cricket"), for: .default)

if You put the navigation bar hidden for the application you have to show it on view did load or appear by :
override func viewWillAppear(_ animated: Bool) {
print("\n Debugger : View will appear called")
self.navigationController?.isNavigationBarHidden = false
}
if you want your navigation bar only show in a specific view controller you have to disappear the navigation bar by :
override func viewDidDisappear(_ animated: Bool) {
print("\n Debugger : View did disapper called")
self.navigationController?.isNavigationBarHidden = true
}
Navigation bar setup Method
private func navigationBarSetup(){
print("\n Debugger : Navigation Bar setup method called")
self.navigationController!.navigationBar.setBackgroundImage(UIImage(named: "your image name "), for: .default)
let backButton = UIBarButtonItem(image: UIImage(named: "your Image name"), style: .plain, target: self, action: #selector(Your selector method))
backButton.tintColor = UIColor.white
self.navigationItem.leftBarButtonItem = backButton
let rightButton = UIBarButtonItem(image: UIImage(named: "your Image name"), style: .plain, target: self, action: #selector(Your selector method))
backButton.tintColor = UIColor.white
self.navigationItem.rightBarButtonItem = rightButton
}

Add the following code to didFinishLaunchingWithOptions method in AppDelegate.swift:
if let myImage = UIImage(named: "navBarImage.jpg"){
UINavigationBar.appearance().setBackgroundImage(myImage, for: .default)
}

#benLIVE asked for how to do a back button, which I was doing when I found the accepted answer, so I thought I'd leave this here too (if a bit late) b/c if you are going to replace a nav bar icon, you may as well replace all of them!
let cubeIcon = UIImageView(image: yourImage)
cubeIcon.contentMode = .scaleAspectFit
self.navigationItem.backBarButtonItem?.image = cubeIcon.image

Related

Hide Back Button Title on iOS 13

Our application has a deployment target of iOS 10. We're hiding all back button titles (for the entire app) with the following code
let attributes: [NSAttributedString.Key : Any] = [
.font : UIFont.systemFont(ofSize: 0.001),
.foregroundColor: UIColor.clear
]
let barButtonItemAppearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self])
barButtonItemAppearance.setTitleTextAttributes(attributes, for: .normal)
barButtonItemAppearance.setTitleTextAttributes(attributes, for: .highlighted)
This worked up until iOS 13, where the back button titles are no longer hidden.
I saw the WWDC 2019 video about the new apperance APIs, but as far as I can tell it only told me how to use the new APIs for a single navigation bar (and not for the entire app).
How can I achieve this?
Add in viewDidLoad() method of the parent(previous in the stack) controller.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
In the next screen, only the arrow image will be presented.
or you can put this code before pushViewController method, for example
func presentNextScreen(_ controller: UIViewController){
// Suppress title in the back button on the next screen.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
self.navigationController?.pushViewController(controller, animated: true)
}
For me, the easiest way to hide the title in the back button is to configure the appearance of UINavigationBar
if #available(iOS 13.0, *) {
let standartAppearence = UINavigationBarAppearance()
standartAppearence.configureWithDefaultBackground()
let backButtonAppearence = UIBarButtonItemAppearance()
let titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.clear]
backButtonAppearence.normal.titleTextAttributes = titleTextAttributes
backButtonAppearence.highlighted.titleTextAttributes = titleTextAttributes
standartAppearence.backButtonAppearance = backButtonAppearence
UINavigationBar.appearance().standardAppearance = standartAppearence
UINavigationBar.appearance().compactAppearance = standartAppearence
UINavigationBar.appearance().scrollEdgeAppearance = standartAppearence
}
In addition, here you can add any other configuration of the navigation bar
A workaround:
Create a base class: BaseViewController.
class BaseViewController: UIViewController {
func hideBackButton() {
self.navigationItem.leftBarButtonItem = nil
}
func hideCloseButton() {
self.navigationItem.rightBarButtonItem = nil
}
override public func viewDidLoad() {
super.viewDidLoad()
addNavigationButtons()
}
func addNavigationButtons() {
let backButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(goBack))
self.navigationItem.leftBarButtonItem = backButton
let closeButton = UIBarButtonItem(image: UIImage(named: "close"), style: .plain, target: self, action: #selector(closeTheFlow))
self.navigationItem.rightBarButtonItem = closeButton
}
#objc func goBack() {
//Go Back
}
#objc func closeTheFlow() {
//Close
}
Make every ViewController a subclass of BaseViewController.
You could do anything with the right and left buttons in the entire app.
I hide title gloabal. a trick
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -UIScreen.main.bounds.size.width, vertical: 0), for: UIBarMetrics.default)

Back UIBarButtonItem appearance remove text and change image

I've watched a lot of questions like this and didn't find an answer for my question.
That how i do now:
APPDELEGATE (didFinishLaunchingWithOptions)
// Text
let barButtonItem = UIBarButtonItem.appearance()
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.normal)
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.highlighted)
// Image
let backImage = UIImage(named: "arrow_left"
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
And this almost fit to what i need, but the screen title shifted to the right as there is an invisible back button text. And it definetly is (the root controller's title has 9 characters length):
The question is: How to change image, hide text and keep standart back action for every appearance of back button in ios 9.0 ?
There are three ways to do what you want.
I recommend: Create your own Navigation Class by extending and UINavigationController and override backbuttonItem (UIBarButtonItem) property to customise it according to your requirement. And use the same Navigation Controller class in your project.
Create a custom backBarButton by extending UIBarButtonItem and manually set the same as a back button of default Navigation Controller class, in all view controller.
Hide default navigation bar from root controller and create your own navigation bar using UIView and UIButton in all view controllers. (I always use this choice, that makes customization of navigation bar very easy for me. And I can set my view according to my requirement)
Here is how you can add Custom button for your navigation bar
let btnleft : UIButton = UIButton(frame: CGRect(x:0, y:0, width:35, height:35))
btnleft.contentMode = .center
btnleft.setImage(Set_Local_Image("arrow_left"), for: .normal)
btnleft.addTarget(self, action: #selector(YOUR_ACTION), for: .touchDown)
let backBarButon: UIBarButtonItem = UIBarButtonItem(customView: btnleft)
self.navigationItem.setLeftBarButtonItems([menuBarButon], animated:false)
instead of "arrow_left" You can use any image you want
For Default back action you can create function(YOUR_ACTION) and use in selector of back button
navController.popViewController(animated: true)
I can suggest you 2 options. Both require BaseViewController class as a superclass of all your view controllers.
If you are ok with native back button image, just want to remove back button text you can use this subclass:
class BaseViewController: UIViewController {
var navigationTitle: String = ""
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if !navigationTitle.isEmpty {
navigationItem.title = navigationTitle
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationTitle = navigationItem.title ?? ""
navigationItem.title = ""
}
}
If you want to use your custom icon for back button, you should create UIBarButtonItem with your image, add target, selector, handle action of the button. Sample BaseViewController class below:
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let backImage = UIImage(named: "arrow_left")
navigationItem.hidesBackButton = true
guard let navigationController = navigationController else {
return
}
if navigationController.viewControllers.count > 1 {
// we have to set back button only when we have at least 1 controller to go back
navigationItem.leftBarButtonItem = UIBarButtonItem(image: backImage, style: .plain, target: self, action: #selector(backBarButtonAction(sender:)))
}
}
// MARK: Actions
func backBarButtonAction(sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
}
According to https://stackoverflow.com/a/16831482/5790492 there is a way to do this without appearance.
Swift 3.0
extension UIViewController {
func setupCustomBackButton() {
if let controllersCount = navigationController?.viewControllers.count, controllersCount > 1 {
let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 12, height: 20))
backButton.setBackgroundImage(UIImage(named: "arrow_left"), for: .normal)
backButton.contentMode = .left
let backButtonItem = UIBarButtonItem(customView: backButton)
backButton.addTarget(self, action: #selector(self.popCurrentViewController), for: .touchUpInside)
navigationItem.leftBarButtonItem = backButtonItem
navigationItem.hidesBackButton = true
}
}
func popCurrentViewController() {
navigationController?.popViewController(animated: true)
}
}
UINavigationBar.appearance().setBackgroundImage(UIImage(), for:
UIBarPosition.any, barMetrics: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().barTintColor = UIColor.main
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().clipsToBounds = false
UINavigationBar.appearance().backgroundColor = UIColor.main
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName :
(UIFont(name: "Helvetica", size: 18))!, NSForegroundColorAttributeName:
UIColor.white]
Try this code and make changes accordingly to set image, color and other properties
You should watch Mark Moeykens' youtube series on this. He is IMHO one of the best YouTube presenters for UI Design and implementation in Swift.
The play list is https://www.youtube.com/playlist?list=PLHDMmeIMXj8WyvlX5uFmppVn2Pm0bXVr7
Create an extension for UINavigationItem
extension UINavigationItem {
func backBarButtonItem() -> UINavigationItem {
return UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}
}

Create a custom UINavigationcontroller class

I have done the following customisation to my embedded UINavigationcontroller. I've done this in the view controller of the view that will show up as first.
However I'm trying to clean it up so that I don't have this all in my UIView class by creating a separate class that will take care of this. The code I'm currently using
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.navigationController?.navigationBar.backIndicatorImage = backButton
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backButtonHigh
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
What I've tried to do is extend the UInavigationcontroller in a new class like this
class RSRNavigationController: UINavigationController{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.navigationController?.navigationBar.backIndicatorImage = backButton
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backButtonHigh
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
this doesn't work. It will run without problems but it won't actually do anything.
I've also tried to do the following
class RSRNavigationController: UINavigationBar{
override func draw(_ rect: CGRect) {
super.draw(rect)
self.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.backIndicatorImage = backButton
self.backIndicatorTransitionMaskImage = backButtonHigh
//self.backItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
However I can't seem to set the title for the back button.
Does anyone know how to fix this?
Your problem lies here, when you reference navigationController INSIDE your custom navigationController class
Instead of doing
self.navigationController?.navigationBar.backIndicatorImage = backButton
do this
self.navigationBar.backIndicatorImage = backButton
Reason?
Because when you extend your custom class by UINavigationController, it becomes a navigationController itself. And by doing self.navigationController you are telling your app to look for a navigationController within which your custom navigationCOntroller resides. Ofcourse such a nav controller does not exist because your custom navController is the main or the top navController of the app. So just remove the self.navigationController part from your custom class, the rest of the code that you have written in your viewDidLoad should work good.
If you still have any questions feel free to ask
You do not change these properties in the navigation controller itself, you change it in the viewController that is embedded inside a navigation controller.
These customization has to be done in a parent ViewController of your view controllers.
This Answer has more info:
https://stackoverflow.com/a/16913435/4004429
if you just want to custom the backButton of the navigationBar,you can add this code in your child view controller :
func setupLeftBarItem() -> Void {
let originalImage = UIImage.init(named: "leftBatItem")?.withRenderingMode(.alwaysOriginal)
let leftBarItem = UIBarButtonItem.init(image: originalImage, style: .done, target: self, action: #selector(leftBarButtonItemDidTouch))
navigationItem.leftBarButtonItem = leftBarItem
}
func leftBarButtonItemDidTouch() -> Void {
_ = navigationController?.popViewController(animated: true)
}

Custom BackButton on NavigationController not appearing

I'm trying to use a custom back button in UINavigationController but the image is not appearing.
Here's the code:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
self.navigationController!.view.backgroundColor = UIColor.clearColor()
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "Back-50")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "Back-50")
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
I'm not sure what's going wrong with this code.
Maybe, you should use UIAppearance.
Like this
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UINavigationBar appearance] setBackIndicatorImage: [UIImage imageNamed:#"icon-back"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage: [UIImage imageNamed:#"icon-back"]];
return YES;
}
In swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named: "")
UINavigationBar.appearance().backIndicatorImage = UIImage(named: "")
return true
}
If you want just your image to appear as the back button then set the tintColor of the navigationBar to clear color and then set an image based UIBarButtonItem as the backBarButtonItem of navigationItem of the controller.
let backButton = UIBarButtonItem(image: UIImage(named: "back"), style: .Plain, target: self, action: "back")
self.navigationController?.navigationBar.tintColor = UIColor.clearColor()
self.navigationItem.backBarButtonItem = backButton
This will make the default back button image (<) not appear (infact it appears but its in clear color so not visible) and just show the back image.
You have to implement those line of code in the targeted viewcontroller that means the controller you will push, because you want to customize back item button which active only when you push a viewcontroller into navigation controller stack. Your code works for me.
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Back-50"), style: .Plain, target: self, action: "back")
func back(){
self.navigationController?.popViewControllerAnimated(true)
}
Try this
self.navigationItem.hidesBackButton = YES;
UIButton *btnLeft=[UIButton buttonWithType:UIButtonTypeCustom];
btnLeft.frame=CGRectMake(0, 0, 65, 40);
[btnLeft addTarget:self action:#selector(onClickBackBarItem:) forControlEvents:UIControlEventTouchUpInside];
[btnLeft setImage:[UIImage imageNamed:#"image_name"] forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btnLeft];
-(void)onClickBackBarItem:(id)sender
{
// ** your stuff ** //
}
May this help yoy
Try this it`s working for me.
var BackButton : UIBarButtonItem = UIBarButtonItem(image:
UIImage(named: "Back-50"), style: .Plain, target: self, action: "back")
self.navigationItem.leftBarButtonItem = BackButton
func back()
{
// your backcontroller code here....
}

How to remove all navigationbar back button title

When I push a UIViewController, it has some title in back button at new UIViewController, if the title has a lot of text, It does not look good in iPhone 4s So I want to remove it.
If I add some code in prepareForSegue function, it is going to be a trouble.
Any better way to achieve this?
If you want back arrow so following code put into AppDelegate file into didFinishLaunchingWithOptions method.
For Objective-C
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];
For Swift
let BarButtonItemAppearance = UIBarButtonItem.appearance()
BarButtonItemAppearance.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .normal)
Another option give below.
In Objective C
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
In Swift
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
UPDATE :
let BarButtonItemAppearance = UIBarButtonItem.appearance()
let attributes: [NSAttributedStringKey: Any] = [
BarButtonItemAppearance.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .normal)
NSAttributedStringKey.font: UIFont.systemFont(ofSize: 0.1),
NSAttributedStringKey.foregroundColor: UIColor.clear]
BarButtonItemAppearance.setTitleTextAttributes(attributes, for: .normal)
BarButtonItemAppearance.setTitleTextAttributes(attributes, for: .highlighted)
UPDATE SWIFT 4.1 :
let attributes = [NSAttributedStringKey.font: UIFont(name: "Helvetica-Bold", size: 0.1)!, NSAttributedStringKey.foregroundColor: UIColor.clear]
BarButtonItemAppearance.setTitleTextAttributes(attributes, for: .normal)
BarButtonItemAppearance.setTitleTextAttributes(attributes, for: .highlighted)
Using Offset
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-1000, 0), for:UIBarMetrics.default)
Work's like charm on Swift 3
self.navigationController?.navigationBar.topItem?.title = " "
I'm using this line of code in AppDelegate file into didFinishLaunchingWithOptions method to remove the backbutton title.
Swift 2.x
let barAppearace = UIBarButtonItem.appearance()
barAppearace.setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics:UIBarMetrics.Default)
Swift 3.x
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), for:UIBarMetrics.default)
Swift 4.x
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.clear], for: .normal)
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.clear], for: UIControlState.highlighted)
Just need go to your Parent ViewController from where your other ViewControllers are dependent.
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)}
Just copy this code in didFinishLaunchingWithOptions launchOptions
Swift 5
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -1000.0, vertical: 0.0), for: .default)
Swift 4
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-1000.0, 0.0), for: .default)
it is simple. put a space in the title of the back button and ready.
Remember that it has to be in the previous view where you want to remove the text.
On iOS 14 is now present the backButtonDisplayMode property in UINavigationItem class. So, to remove back button title you can use
navigationItem.backButtonDisplayMode = .minimal
in the viewDidLoad func of the viewController where you want remove it.
To remove it in all navigationBar I used the swizzling technique
import UIKit
private let swizzling: (UIViewController.Type, Selector, Selector) -> Void = { forClass, originalSelector, swizzledSelector in
if let originalMethod = class_getInstanceMethod(forClass, originalSelector), let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
let didAddMethod = class_addMethod(forClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(forClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
extension UIViewController {
static func swizzle() {
let originalSelector1 = #selector(viewDidLoad)
let swizzledSelector1 = #selector(swizzled_viewDidLoad)
swizzling(UIViewController.self, originalSelector1, swizzledSelector1)
}
#objc open func swizzled_viewDidLoad() {
if let _ = navigationController {
if #available(iOS 14.0, *) {
navigationItem.backButtonDisplayMode = .minimal
} else {
// Fallback on earlier versions
navigationItem.backButtonTitle = ""
}
}
swizzled_viewDidLoad()
}
}
And in application(_:didFinishLaunchingWithOptions:) call
UIViewController.swizzle()
You could create a subclass for all UIViewControllers you want this behavior for, and in the subclass's viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(
title: "", style: .plain, target: nil, action: nil)
}
This way, you can choose which controllers you want the behavior for, without duplicating code. I prefer my controllers to just say "Back", rather than the title of the previous controller, so I set that title here.
You can use xcode 8 and swift 3.0
self.navigationController?.navigationBar.backItem?.title = " "
let barAppearace = UIBarButtonItem.appearance()
barAppearace.setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), for:UIBarMetrics.default)
used this line of code in swift 3.0
Taking inspiration from rordulu's answer here, I ended up creating a custom UINavigationController and UINavigation bar which seems to handle all cases of this tricky problem.
1) Initialise new UINavigationController with your custom UINavigationBar:
class CustomNavigationController: UINavigationController {
convenience init() {
self.init(navigationBarClass: CustomNavigationBar.self, toolbarClass: nil)
}
}
2) Set the backItem.title property of the navigation bar to an empty string, every time the view lays itself out
class CustomNavigationBar: UINavigationBar {
override func layoutSubviews() {
backItem?.title = ""
super.layoutSubviews()
}
}
Now every time you use this navigation controller and bar combination, it will never have back button text! 🎉
Note: this should work fine if using storyboards also, just ensure to drop the custom navigation bar component into the view
Simple Solution :
While you are pushing 2nd controller from 1st controller, put self.navigationItem.title = "" in viewWillDisappear of 1st controller. It hides back button title from 2nd controller.
Above statment hides 1st controllers title, hence when we came back we want title for 1st controller again. For that we have add title for 1st controller in viewWillAppear method of 1st controller.
Refer following methods (of 1st controller)
override func viewWillDisappear(_ animated: Bool) {
self.navigationItem.title = ""
}
override func viewWillAppear(_ animated: Bool) {
self.navigationItem.title = "Title"
}
Works on Swift 5:
self.navigationItem.backBarButtonItem?.title = ""
Please note it will be effective for the next pushed view controller not the current one on the display, that's why it's very confusing!
Also, check the storyboard and select the navigation item of the previous view controller then type something in the Back Button (Inspector).
A method for iOS13.
let backButtonAppearance = UIBarButtonItemAppearance(style: .plain)
backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.backButtonAppearance = backButtonAppearance
UINavigationBar.appearance().standardAppearance = navigationBarAppearance
I usually add or change the back button in viewDidLoad of the UIViewController.
Something like that should work:
let leftButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "closeView:")
self.navigationItem.leftBarButtonItem = leftButton
Don't forget to change and implement the function that it's called to close the view.
Even easier, just change the title:
self.navigationItem.leftBarButtonItem.title = "Back"
if #available(iOS 14.0, *) {
navigationItem.backButtonDisplayMode = .minimal
} else {
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Swift 3:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
Adding a second answer here as my first only partially works. This method is less elegant in the fact that it requires calling a method in each view in the application, however it works without any side-effects.
So firstly, create a UIViewController extension class with a function to remove back button text and add a custom back button:
extension UIViewController {
func setBackButton() {
navigationController?.navigationBar.backIndicatorImage = R.image.backArrow()
navigationController?.navigationBar.backIndicatorTransitionMaskImage = R.image.backArrow()
navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
}
Secondly, we can simply call out to this function in the viewDidLoad of each view controller you need it in.
Swift 4.2
UIBarButtonItem.appearance().setTitleTextAttributes([.foregroundColor: UIColor.clear], for: .normal)
Updated Answer For Swift 4.2
Working with UIAppearance is a cleaner way of solving the problem but it would cause all the UIBarButtonItem to have a clear text. An improved version of the solution could be to check if the UIBarButtonItem is contained in a UINavigationBar.
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)
Just create extension of UIViewController with override function awakeFromNib() and make UIBarButtonItem with an empty title and give to navigation backBarButtonItem.
extension UIViewController {
open override func awakeFromNib() {
let backBarBtnItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backBarBtnItem
}
}
if you want to remove back button title when you open next screen
do this inside the function initialising and pushing a new screen:
navigationItem.backButtonTitle = ""
Full usage:
let view = SomeView()
let controller = UIHostingController(rootView: view)
navigationItem.backButtonTitle = ""
navigationController?.pushViewController(controller, animated: true)
But to customise back buttons for all navigation bars in your app you need to do this:
func setupNavBarAppearance() {
let backButtonImage = Images.west.image.withAlignmentRectInsets(UIEdgeInsets(top: -5, left: -15, bottom: -5, right: -15))
let backButtonAppearance = UIBarButtonItemAppearance(style: .plain)
backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
let appearance = UINavigationBarAppearance()
appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor : UIColor.white]
appearance.backButtonAppearance = backButtonAppearance
appearance.setBackIndicatorImage(backButtonImage, transitionMaskImage: backButtonImage)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().isTranslucent = false
}
You can call it from your AppDelegate.swift
Swift 4.2 & 5
Instead of playing with the navigation bar tint color which will have side effects if you are using image picker anytime later in your code.
Use below code:
extension UIViewController {
open override func awakeFromNib() {
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
Call it from your first ViewController:
self.awakeFromNib()
Put the below code in any of the UIViewcontroller extension it will hide all the UIViewcontroller back text
open override func awakeFromNib() {
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
I have a simple solution for those, who don't want to use method swizzling or duplicating a similar code in different view controllers.
To remove back button title, create a UINavigationController subclass and override pushViewController(_, animated:) method:
final class CustomNavigationController: UINavigationController {
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
let backBarButtonItem = UIBarButtonItem()
backBarButtonItem.title = nil
viewController.navigationItem.backBarButtonItem = backBarButtonItem
}
}
I don't know why but I found problem with hiding back button title in iPhone pluses but in device without plus shows correct with
leftBarButtonItem.title = ""
So I found simple way. It is set tint color to clear in NavigationBar of NavigationViewController in autolayout. It may be problem if you use icons or text tiles with tint. But in my case I don't use it as all.
Just use this:
func removeBackButton(vc:UIViewController) {
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named:""), for: .normal)
let leftBarButton = UIBarButtonItem.init(customView: button)
vc.navigationItem.leftBarButtonItem = leftBarButton
}
So call this method in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
removeBackButton(vc:self)
}
You can add this extension to UIViewController
And then call this function in every viewDidLoad()
like : self.updateBackButton()
extension UIViewController {
func updateBackButton(){
if self.navigationController != nil {
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .done, target: self, action: nil)
}
}}
I would like to share a solution that works for me. Also, it can be adjusted base on your needs and requirements.
Note, in my case, I use a storyboard to specify CustomNavigationBar
Swift 4.2
class CustomNavigationBar: UINavigationBar {
override func awakeFromNib() {
super.awakeFromNib()
guard let topItem = topItem else { return }
removeBackButtonTitle(for: topItem)
}
override func pushItem(_ item: UINavigationItem, animated: Bool) {
removeBackButtonTitle(for: item)
super.pushItem(item, animated: animated)
}
func removeBackButtonTitle(for item: UINavigationItem) {
item.backBarButtonItem = UIBarButtonItem()
}
}
Works for Swift 4.2
Using the line of code in AppDelegate file into didFinishLaunchingWithOptions
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .highlighted)

Resources