24

I was able to create a UIBarButton item that can go back programmatically using the following code:

    func backAction() -> Void {        
        self.navigationController?.popViewControllerAnimated(true)
    }
override func viewDidLoad() {
        super.viewDidLoad()
    let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "backAction")

        self.navigationItem.leftBarButtonItem = backButton
    }

The problem is that the back button doesn't have the left pointing arrow: enter image description here Is there a way to make it look like a regular back button with the arrow like this: enter image description here

I would also like to know if there is a way to make the button title names as the title of the previous view controller, if that's possible.

Thanks

Dennis Vennink
  • 1,083
  • 1
  • 7
  • 23
Rami Ammoun
  • 855
  • 2
  • 10
  • 25

7 Answers7

48

Below is the code by using UIButton with image you can add it as a customView for UIBarButtonItem

override func viewDidLoad() {
    super.viewDidLoad()
    var backbutton = UIButton(type: .Custom)
    backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal) // Image can be downloaded from here below link 
    backbutton.setTitle("Back", forState: .Normal)
    backbutton.setTitleColor(backbutton.tintColor, forState: .Normal) // You can change the TitleColor
    backbutton.addTarget(self, action: "backAction", forControlEvents: .TouchUpInside)

    self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}

func backAction() -> Void {        
   self.navigationController?.popViewControllerAnimated(true)
}

BackButton.png Download Link

For setting the title of backbutton with the previous view controller title you have to pass the Title as a String while presenting the controller make change to above code as

var titleStrFromPreviousController: String // This value has to be set from previous controller while presenting modal controller
backbutton.setTitle(titleStrFromPreviousController, forState: .Normal)

This may help.

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()

    addBackButton()
}

func addBackButton() {
    let backButton = UIButton(type: .custom)
    backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
    backButton.setTitle("Back", for: .normal)
    backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
    backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)

    self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}

@IBAction func backAction(_ sender: UIButton) {
   let _ = self.navigationController?.popViewController(animated: true)
}
byJeevan
  • 3,728
  • 3
  • 37
  • 60
sKhan
  • 9,694
  • 16
  • 55
  • 53
  • 1
    you should follow https://developer.apple.com/ios/human-interface-guidelines/icons-and-images/custom-icons/ for image size – sKhan Jan 29 '18 at 16:27
  • in swift add backButton.frame = CGRect(x: 0, y: 0, width: 100, height: 25) or something – djdance Feb 11 '19 at 09:26
13

Updated for Swift 4.2 - thanks to sam bing and silentbeep

Made some modifications on some colors and action's selector.

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .blue
        self.navigationItem.title = title
        self.navigationController?.navigationBar.barTintColor = .white
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: makeBackButton())
    }

    func makeBackButton() -> UIButton {
        let backButtonImage = UIImage(named: "backbutton")?.withRenderingMode(.alwaysTemplate)
        let backButton = UIButton(type: .custom)
        backButton.setImage(backButtonImage, for: .normal)
        backButton.tintColor = .blue
        backButton.setTitle("  Back", for: .normal)
        backButton.setTitleColor(.blue, for: .normal)
        backButton.addTarget(self, action: #selector(self.backButtonPressed), for: .touchUpInside)
        return backButton
    }

    @objc func backButtonPressed() {
        dismiss(animated: true, completion: nil)
//        navigationController?.popViewController(animated: true)
    }
Newsonic
  • 413
  • 4
  • 19
  • With this solution, you will get the custom button, but you will lose the drag left-to-right to go back to the previous view controller. The only way to go back will be to press the button. – christostsang Jul 14 '21 at 05:12
4

You can do by embedding your view in a navigation controller. Here is an image showing how to do that: navigationController

Hope it helps :D

Pixele9
  • 422
  • 8
  • 25
4

For future searches, I wanted to add that you can now use the default icon by this code:

override public func viewDidLoad() {
    // create chevron image
    let config = UIImage.SymbolConfiguration(pointSize: 25.0, weight: .medium, scale: .medium)
    let image = UIImage(systemName: "chevron.left", withConfiguration: config)

    // create back button
    let backButton = UIButton(type: .custom)
    backButton.addTarget(self, action: #selector(self.close(_:)), for: .touchUpInside)
    backButton.setImage(image, for: .normal)
    backButton.setTitle("Back", for: .normal)
    backButton.setTitleColor(backButton.tintColor, for: .normal)
    self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}

@IBAction func close(_ sender: UIButton) {
    self.navigationController?.dismiss(animated: true, completion: nil)
}
1

The first answer works great however the image is a bit too big so use the preview and scale it down to width:13 and height: 22, also set its rendering mode to .alwaysTemplate and change the UIButton's tint to white, while also adding two spaces before the string : " Back". This will result in something that is quiet similar to the navigation bar back button, the image could be better in terms of size and placement.

Edited code:

     func addBackButton() {


            let backButtonImage = UIImage(named: "BackButton.png")?.withRenderingMode(.alwaysTemplate)

            let backButton = UIButton(type: .custom)
            backButton.setImage(backButtonImage, for: .normal) 
            backButton.tintColor = .white
            backButton.setTitle("  Back", for: .normal)
            backButton.setTitleColor(.white, for: .normal)
            backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)

            self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)


}
Sam Bing
  • 2,794
  • 1
  • 19
  • 29
1

I changed one last line of code from selected answer and it works for me.

override func viewDidLoad() {
    super.viewDidLoad()

    addBackButton()
}

func addBackButton() {
    let backButton = UIButton(type: .custom)
    backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
    backButton.setTitle("Back", for: .normal)
    backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
    backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)

    self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}

@IBAction func backAction(_ sender: UIButton) {
   let _ = self.dismiss(animated: true, completion: nil)
}
Daehue Kim
  • 62
  • 9
0

Swift 5

override func viewDidLoad() {
            super.viewDidLoad()
            let backbutton = UIButton(type: .custom)
            backbutton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
            backbutton.setTitle("Back", for: .normal)
            backbutton.setTitleColor(backbutton.tintColor, for: .normal) // You can change the TitleColor
            backbutton.addTarget(self, action: Selector(("backAction")), for: .touchUpInside)
    
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
        }
    
        func backAction() -> Void {
            self.navigationController?.popViewController(animated: true)
        }
Karan Mehra
  • 339
  • 3
  • 12