【问题标题】:How to remove all navigationbar back button title如何删除所有导航栏后退按钮标题
【发布时间】:2015-07-06 21:28:22
【问题描述】:

当我按下UIViewController时,它在新UIViewController的后退按钮中有一些标题,如果标题有很多文字,在iPhone 4s上看起来不太好,所以我想删除它。

如果我在prepareForSegue函数中添加一些代码,那就麻烦了。

有没有更好的方法来实现这一点?

【问题讨论】:

标签: ios swift uibarbuttonitem


【解决方案1】:

如果您想要返回箭头,请将以下代码放入 AppDelegate 文件中的 didFinishLaunchingWithOptions 方法中。

For Objective-C

 [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];

For Swift

let BarButtonItemAppearance = UIBarButtonItem.appearance()
BarButtonItemAppearance.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .normal)

下面给出另一个选项。

Objective C

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

Swift

self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)

更新:

    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)

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

使用偏移量

UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-1000, 0), for:UIBarMetrics.default)

【讨论】:

  • setBackButtonTitlePositionAdjustment 并不总是有效,当后退按钮标题很长,但不足以更改为“返回”时,中间的标题会向右移动。
  • @zgjie 这只是你的偏移量有多大的主题。您可以轻松地将 '-60' 替换为 '-6000' 而忘记这个问题
  • 这里稍微精确一点,标题属于PREVIOUS视图控制器。所以记得在 presentViewController 或 pushViewController 方法之前设置它。
  • 嗯,这在 AppDelegate 中不起作用。 “AppDelegate 类型的值没有成员 navigationItem”
  • @DominikBucher 我已经为这种行为创建了一个类别,它隐藏了应用程序中每个位置的后退按钮标题,有点像"NON HACKY" way,只需在项目中添加类别就可以了。我强烈不同意使用setBackButtonTitlePositionAdjustment:forBarMetrics: 设置位置的解决方案,如果用户从可访问性设置中启用了按钮形状,则该形状最终会显示为丑陋的导航栏。
【解决方案2】:

工作就像 Swift 3 的魅力

self.navigationController?.navigationBar.topItem?.title = " "

【讨论】:

  • 这是使用navigationController?.pushViewController(_, animated:)时唯一有效的方法
  • 谢谢,伙计。这是唯一一个成功的。干杯。
  • Swift 4 也为我工作
  • @MaksimKniazev,这个问题有什么解决办法吗?我在viewWillAppear:中找到了再次更新标题的唯一解决方案。
  • 这会删除前一个视图的标题
【解决方案3】:

我正在使用AppDelegate文件中的这行代码到didFinishLaunchingWithOptions方法中删除后退按钮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)

【讨论】:

  • setBackButtonTitlePositionAdjustment 并不总是有效,当后退按钮标题很长,但还不足以更改为“返回”时,中间的标题会向右移动。
  • 这不是一个理想的解决方案。如果我们设置任何导航标题而不更改左侧导航栏项目的标题,标题将向右移动,因为左侧导航栏标题插入。
  • 在 iOS 11 中它打破了后退按钮的位置。它低于原来的位置
  • 这应该如何工作?文本仍可通过 VoiceOver 访问。
  • 这会产生问题,当取消或完成 barbuttonitem 在呈现图像选择器或其他东西时不可见
【解决方案4】:

只需将此代码复制到didFinishLaunchingWithOptions launchOptions

斯威夫特 5

UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -1000.0, vertical: 0.0), for: .default)

斯威夫特 4

UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-1000.0, 0.0), for: .default)

【讨论】:

  • 不适用于 iOS 15、xCode 13
【解决方案5】:

只需要从您的其他 ViewController 所依赖的位置转到您的 父 ViewController

override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)}

【讨论】:

    【解决方案6】:

    这很简单。在后退按钮的标题中放置一个空格并准备就绪。 请记住,它必须在您要删除文本的上一个视图中。

    【讨论】:

    • 最佳解决方案 IMO。不需要您将整个应用程序设置为特定的清晰样式,这可能会产生使任何文本 barbuttonitems 消失的副作用。如果它提到如果没有导航项,您必须将导航项拖到您的控制器,答案可能会更好。
    【解决方案7】:

    在 iOS 14 上,backButtonDisplayMode 属性现在存在于 UINavigationItem 类中。因此,要删除后退按钮标题,您可以使用

    navigationItem.backButtonDisplayMode = .minimal
    

    在 viewController 的 viewDidLoad 函数中,您要在其中删除它。

    为了在所有导航栏中删除它,我使用了 swizzling 技术

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

    并在application(_:didFinishLaunchingWithOptions:) 通话中

    UIViewController.swizzle()
    

    【讨论】:

    • 很高兴了解 .minimal,但您需要在将当前视图控制器推入堆栈的导航控制器上进行设置。不幸的是,您不能只在显示视图控制器上设置它...
    【解决方案8】:

    您可以为您想要此行为的所有UIViewControllers 创建一个子类,并在子类的viewDidLoad 中:

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.backBarButtonItem = UIBarButtonItem(
            title: "", style: .plain, target: nil, action: nil)
    }
    

    这样,您可以选择您想要的行为的控制器,而无需重复代码。我更喜欢我的控制器只说“返回”,而不是前一个控制器的标题,所以我在这里设置了这个标题。

    【讨论】:

      【解决方案9】:

      你可以使用 xcode 8 和 swift 3.0

      self.navigationController?.navigationBar.backItem?.title = " "
      

      【讨论】:

      • 这不会完全从以前的视图控制器中删除标题吗?
      • 是的,它将删除从self.navigationController推送的所有ViewControllers 的标题
      【解决方案10】:
      let barAppearace = UIBarButtonItem.appearance()
      barAppearace.setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), for:UIBarMetrics.default)
      

      在swift 3.0中使用了这行代码

      【讨论】:

      • 会影响 UISearchController 的取消按钮
      【解决方案11】:

      rordulu's 答案here 中汲取灵感,我最终创建了一个自定义 UINavigationController 和 UINavigation 栏,似乎可以处理这个棘手问题的所有情况。

      1) 使用您的自定义UINavigationBar 初始化新的UINavigationController

      class CustomNavigationController: UINavigationController {
      
          convenience init() {
              self.init(navigationBarClass: CustomNavigationBar.self, toolbarClass: nil)
          }
      }
      

      2) 将导航栏的backItem.title 属性设置为空字符串,每次视图自行布局时

      class CustomNavigationBar: UINavigationBar {
      
          override func layoutSubviews() {
              backItem?.title = ""
              super.layoutSubviews()
          }
      }
      

      现在每次你使用这个导航控制器和栏的组合,它永远不会有返回按钮文本! ?

      注意:如果还使用故事板,这应该可以正常工作,只需确保将自定义导航栏组件放入视图中

      【讨论】:

      • 非常感谢!这是最好的方法,应该是正确的答案:)
      • 刚刚意识到这有一个副作用,它会完全擦除导航项标题。所以当前一个视图显示时,它不会有标题!我将继续寻找这个烦人问题的完美解决方案。
      • 该死的你是对的。我怎么能错过!如果您找到解决此问题的方法,请告诉我。谢谢
      • 你能找到完美的解决方案@HarryBloom吗?
      • @Hemang 不是一个完美的解决方案,但我发现了一些可行的方法。在这里添加了第二个答案stackoverflow.com/a/49094282/1532838
      【解决方案12】:

      我通常在 UIViewController 的 viewDidLoad 中添加或更改返回按钮。

      类似的东西应该可以工作:

      let leftButton = UIBarButtonItem(title: "Back", style:     UIBarButtonItemStyle.Plain, target: self, action: "closeView:")
      self.navigationItem.leftBarButtonItem = leftButton
      

      不要忘记更改并实现关闭视图所调用的函数。

      更简单,只需更改标题:

      self.navigationItem.leftBarButtonItem.title = "Back"
      

      【讨论】:

      • 这打破了 iOS 对从左向右滑动导航返回的内置支持,恕我直言,打破这一点的应用真的很烦人。
      【解决方案13】:

      简单的解决方案:

      当您从第一个控制器推动第二个控制器时,将 self.navigationItem.title = "" 放入第一个控制器的 viewWillDisappear 中。它隐藏了第二个控制器的后退按钮标题。

      上面的语句隐藏了第一个控制器的标题,因此当我们回来时,我们再次想要第一个控制器的标题。为此,我们在第一个控制器的 viewWillAppear 方法中为第一个控制器添加标题

      参考以下方法(第一个控制器)

          override func viewWillDisappear(_ animated: Bool) {
          self.navigationItem.title = ""
      }
      
      override func viewWillAppear(_ animated: Bool) {
          self.navigationItem.title = "Title"
      }
      

      【讨论】:

        【解决方案14】:

        iOS13 的一种方法。

        let backButtonAppearance = UIBarButtonItemAppearance(style: .plain)
        backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
        
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.backButtonAppearance = backButtonAppearance
        
        UINavigationBar.appearance().standardAppearance = navigationBarAppearance
        

        【讨论】:

          【解决方案15】:

          斯威夫特 3:

          self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
          

          【讨论】:

            【解决方案16】:

            在此处添加第二个答案,因为我的第一个答案仅部分有效。这种方法不太优雅,因为它需要在应用程序的每个视图中调用一个方法,但是它可以在没有任何副作用的情况下工作。

            首先,创建一个 UIViewController 扩展类,其中包含删除后退按钮文本并添加自定义后退按钮的功能:

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

            其次,我们可以在您需要它的每个视图控制器的viewDidLoad 中简单地调用此函数。

            【讨论】:

              【解决方案17】:

              斯威夫特 4.2

              UIBarButtonItem.appearance().setTitleTextAttributes([.foregroundColor: UIColor.clear], for: .normal)
              

              【讨论】:

              • 图像选择器的取消和完成按钮在这种方法中消失了
              【解决方案18】:

              Swift 4.2 的更新答案

              使用UIAppearance 是解决问题的一种更简洁的方法,但它会导致所有UIBarButtonItem 都具有清晰的文本。解决方案的改进版本可能是检查UIBarButtonItem 是否包含在UINavigationBar 中。

                  UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)
              

              【讨论】:

                【解决方案19】:

                只需使用覆盖函数awakeFromNib() 创建UIViewController 的扩展名,并将UIBarButtonItem 设为空标题并提供给navigation backBarButtonItem

                extension UIViewController {
                
                  open override func awakeFromNib() {
                    let backBarBtnItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
                    navigationItem.backBarButtonItem = backBarBtnItem
                  }
                
                }
                

                【讨论】:

                  【解决方案20】:

                  适用于 Swift 5

                          self.navigationItem.backBarButtonItem?.title = ""
                  

                  请注意,它对下一个推送的视图控制器而不是当前显示的视图控制器有效,这就是为什么它非常令人困惑!

                  另外,检查情节提要并选择 previous 视图控制器的导航项,然后在 Back Button(Inspector)中输入一些内容。

                  【讨论】:

                  • title 不是 get 属性,请查看 Apple 文档
                  【解决方案21】:

                  如果您想在打开下一个屏幕时删除返回按钮标题

                  在初始化并推送新屏幕的函数中执行此操作:

                  navigationItem.backButtonTitle = ""
                  

                  完全使用:

                      let view = SomeView()
                      let controller = UIHostingController(rootView: view)
                      navigationItem.backButtonTitle = ""
                      navigationController?.pushViewController(controller, animated: true)
                  

                  但要为应用中的所有导航栏自定义后退按钮,您需要这样做:

                  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
                  }
                  

                  你可以从你的 AppDelegate.swift 调用它

                  【讨论】:

                    【解决方案22】:

                    Swift 4.2 和 5

                    如果您稍后在代码中使用图像选择器,而不是使用导航栏色调颜色,这将产生副作用。

                    使用下面的代码:

                    extension UIViewController {
                            open override func awakeFromNib() {
                                navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
                        }  
                    }
                    

                    从你的第一个 ViewController 调用它:

                    self.awakeFromNib()
                    

                    【讨论】:

                      【解决方案23】:

                      将下面的代码放在任何UIViewcontroller extension 中,它将隐藏所有UIViewcontroller 后面的文本

                      open override func awakeFromNib() {
                              navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
                          }
                      

                      【讨论】:

                        【解决方案24】:

                        对于那些不想在不同的视图控制器中使用方法调配或复制类似代码的人,我有一个简单的解决方案。

                        要删除返回按钮标题,创建一个 UINavigationController 子类并重写 pushViewController(_, animated:) 方法:

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

                        【讨论】:

                          【解决方案25】:
                              if #available(iOS 14.0, *) {
                                  navigationItem.backButtonDisplayMode = .minimal
                              } else {
                                  navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
                              }
                          

                          【讨论】:

                            【解决方案26】:

                            我不知道为什么,但我发现在 iPhone pluses 中隐藏后退按钮标题存在问题,但在没有 plus 的设备中,使用

                            显示正确
                            leftBarButtonItem.title = ""
                            

                            所以我找到了简单的方法。它在自动布局中的 NavigationViewController 的 NavigationBar 中设置了要清除的色调。如果您使用带有色调的图标或文本块,则可能会出现问题。但就我而言,我并没有完全使用它。

                            【讨论】:

                              【解决方案27】:

                              就用这个吧:

                              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
                              }
                              

                              所以在viewDidLoad中调用这个方法:

                              override func viewDidLoad() {
                                      super.viewDidLoad()
                                   removeBackButton(vc:self)
                              }
                              

                              【讨论】:

                                【解决方案28】:

                                您可以将此扩展添加到 UIViewController 然后在每个 viewDidLoad() 中调用这个函数 比如:self.updateBackButton()

                                extension UIViewController {
                                func updateBackButton(){
                                    if self.navigationController != nil {
                                        self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .done, target: self, action: nil)
                                    }
                                }}
                                

                                【讨论】:

                                  【解决方案29】:

                                  我想分享一个适合我的解决方案。此外,它可以根据您的需要和要求进行调整。

                                  注意,在我的例子中,我使用故事板来指定 CustomNavigationBar

                                  斯威夫特 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()
                                      }
                                  }
                                  

                                  【讨论】:

                                    【解决方案30】:

                                    适用于 Swift 4.2

                                    使用AppDelegate文件中的代码行到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)
                                    

                                    【讨论】:

                                    • 这隐藏了后栏按钮文本,但不幸的是导航栏标题没有居中