-1

I do not want to see the "Back" text that is displayed automatically when going to a view controller with no Title. I would like this to happen everywhere on my application, is there a few lines of code I can put in the app delegate to make this possible?

I have tried a few approaches from SO before posting this question and have found no success. I want to this in Swift, not Obj-c.

I tried this with no success; it ran fine, but the back text was still displayed in the next view controller.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let backItem = UIBarButtonItem()
    backItem.title = "Something Else"
    navigationItem.backBarButtonItem = backItem // This will show in the next view controller being pushed
}

I would like to put this in app delegate so it would happen throughout my application rather than having to put that into every single swift file in my project. Anybody have any ideas?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Trenton Tyler
  • 1,692
  • 3
  • 24
  • 53

2 Answers2

0

There are several different ways to do this. I’ll present a solution that gives you a bit more flexability as you’ll want to display a button some times, hide other times, and customize at other times. This example assumes you are using Navigation Controller based UI, but can be adapted to other types.

Whenever I create an app I like to create my own UIViewController class and have all of my UIViewControllers inherit from this single view controller. If I want to customize something for all my UIViewControllers I can do this at my new super class level since all the other views inherit from that.

In my sample code below I create my custom UIViewController called MasterViewController. I have all of my UIViewControllers inherit from it: ViewController, ViewController2 & ViewController3. Read the notes in the code below to understand what’s going on.

NOTE: Make sure you check for the case where the UIViewController should not have the back button as this would be the case where there is nothing to return to. You can add this code to MasterViewController but I did not for this sample.

//=========================================================
//MasterViewController
//=========================================================
// Master View Controller that all UIViewControllers inherit from.

import UIKit

class MasterViewController: UIViewController {
    // This will be title if the user doesn't change it in a subclass.
    var backButtonTitle = "Default Back Title"

    override func viewDidLoad() {
    // This resets the default back button to always be shown unless the user calls createCustomBackButtonWithTitle from child class.
        self.navigationItem.hidesBackButton = false
        super.viewDidLoad()
    }

    func createCustomBackButtonWithTitle(customTitle: String) {
        // Hide the default back button.
        self.navigationItem.hidesBackButton = true

        // Programmatically create custom back button.
        let backButton = UIBarButtonItem(title: customTitle, style: UIBarButtonItemStyle.Plain, target: self, action: "goBack:")
        self.navigationItem.leftBarButtonItem = backButton
    }

    @IBAction func goBack(sender: UIButton!) {
        navigationController?.popViewControllerAnimated(true)
    }
}
//=========================================================
//ViewController
//=========================================================
// This view controller customizes the back name and inherits the default "go back" behavior from MasterViewController.

import UIKit

class ViewController: MasterViewController {
    override func viewDidLoad() {
    super.viewDidLoad()
    createCustomBackButtonWithTitle("ButtonName")
    }
}
//=========================================================
//ViewController2
//=========================================================
// This view controller customizes the back name but overrides the default "goBack" behavior from MasterViewController to do something different

import UIKit

class ViewController2: MasterViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        createCustomBackButtonWithTitle("ButtonName 2")
    }

    // Override the back button behavior from super class because we don't want default "back" behavior.
    @IBAction override func goBack(sender: UIButton!) {
    // Costume Code here
    }
}
//=========================================================
//ViewController3
//=========================================================
// This view controller inherits from MasterViewController, but gets the default "back" behavior from a normal
// UINavigationController since it never calls createCustomBackButtonWithTitle to change the behavior

import UIKit

class ViewController3: MasterViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
xdeleon
  • 769
  • 8
  • 20
  • Please *don't* do this. See my answer for details. – NRitH Dec 10 '15 at 19:10
  • 1
    @NRitH, Point made. I have not run into this situation, but I'm sure 200 view controllers was painful. So I'm thinking I should just leave my answer so others can see your comments and why it would be bad? Or I should just delete that answer? Still learning the ropes on SO. – xdeleon Dec 10 '15 at 19:18
  • No, go ahead and keep it; it's in line with almost all other answers on this subject here. I just found, through a lot of trial and error, another way to do it, and someday I'll get around to publishing a tutorial on it. – NRitH Dec 10 '15 at 19:21
  • Ok, praying to the SO gods that leaving here was the right thing to do as any down votes won't be good for me. But going to take one for the team. Live and learn... – xdeleon Dec 10 '15 at 19:24
0

Most people wind up doing something like @xdeleon suggested, but I highly recommend not doing that, if for no other reason that that you'll break the built-in swipe behavior to navigate backwards in the view controller stack. There are a couple answers on SO that tell you how to restore this back-swipe functionality, but as someone who's had to fix this in an existing app with 200+ view controllers, I'd like to save you a lot of pain.

If you don't mind working in storyboards, then make sure that each of your view controllers' navigation item's back button text is an empty string. However, since that's a lot to keep track of, it's marginally easier to do in code, and the only way I've found works perfectly is to create a cachedTitle instance variable on your view controller, and implement the view controller's viewWillAppear() and viewWillDisappear() methods like so:

override func viewWillAppear(animated: Bool) {
    // Reset the view controller's title only if it doesn't already have one.
    if (navigationItem.title == nil || navigationItem.title == "") && navigationItem.titleView == nil {
        navigationItem.title = cachedTitle
    }
}

override func viewWillDisappear(animated: Bool) {
    if navigationItem.title != nil {    // not 'if let'!
        cachedTitle = navigationItem.title
        navigationItem.title == ""
    }
}

You can either put these methods in a UIViewController subclass that all of your view controllers extend, or, better yet, put these in custom methods in a category on UIViewController, and just call them in your view controllers' viewWillAppear() and viewWillDisappear() calls.

If you want to use something other than the back button's '<' symbol, don't add a custom back or left button; just set a custom back indicator image and mask on the navigation bar.

NRitH
  • 13,441
  • 4
  • 41
  • 44