Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add NSAttributedString to UIBarButtonItem

I'm attempting to set an attributed string on my back bar button item.
This is my first attempt at attributed strings.
Here is the code:

    self.navigationItem.hidesBackButton = true
    let barButtonBackStr = "< Back"
    var attributedBarButtonBackStr = NSMutableAttributedString(string: barButtonBackStr as String)
    attributedBarButtonBackStr.addAttribute(NSFontAttributeName,
        value: UIFont(
            name: "AmericanTypewriter-Bold",
            size: 18.0)!,
        range: NSRange(
            location:0,
            length:1))
    let newBackButton = UIBarButtonItem(title: attributedBarButtonBackStr, style: UIBarButtonItemStyle.Plain, target: self, action: "barButtonBack:")
    self.navigationItem.leftBarButtonItem = newBackButton

This results in the following error in Xcode.

Cannot invoke initializer for type 'UIBarButtonItem' with an argument list of type '(title: NSMutableAttributedString, style: UIBarButtonItemStyle, target: CombatOutcomeViewController, action: String)'

Anyone have an idea on how to do this? Thanks.

like image 315
Juio Avatar asked Dec 05 '22 20:12

Juio


1 Answers

You cannot directly set an attributed string to an UIBarButtonItem. You have to set a normal string to its title and then set the attributes for the title:

let barButtonBackStr = "< Back"
let attributes: [NSAttributedString.Key : AnyObject] = [.font : UIFont(name: "AmericanTypewriter-Bold", size: 18)!]
let newBackButton = UIBarButtonItem(title: barButtonBackStr, style: .plain, target: self, action: "barButtonBack:")
newBackButton.setTitleTextAttributes(attributes, for: .normal)
navigationItem.leftBarButtonItem = newBackButton

This approach has one caveat: You cannot set a range for the attributes. It's all or nothing.

To define a range for the attributes you have to create a UILabel, set an attributed string to its attributedText property and then create a UIBarButtonItem with a custom view:

let barButtonBackStr = "< Back"
let attributedBarButtonBackStr = NSMutableAttributedString(string: barButtonBackStr as String)
attributedBarButtonBackStr.addAttribute(NSAttributedString.Key.font,
    value: UIFont(
        name: "AmericanTypewriter-Bold",
        size: 18.0)!,
    range: NSRange(
        location:0,
        length:1))
let label = UILabel()
label.attributedText = attributedBarButtonBackStr
label.sizeToFit()
let newBackButton = UIBarButtonItem(customView: label)
self.navigationItem.leftBarButtonItem = newBackButton

When you want to use this approach you have to know you have to set the target and the action to the custom view, because the UIBarButtonItem does not longer handle it. As it says in Apple's docs:

The bar button item created by this method does not call the action method of its target in response to user interactions. Instead, the bar button item expects the specified custom view to handle any user interactions and provide an appropriate response.

like image 158
joern Avatar answered Jan 09 '23 04:01

joern