1

I have a UIBarButton in my navigation bar, I set an image (silhouette.png) to it from the storyboard, and I can change that image's tint (color) at will:

    if let num2 = Int(s, radix: 16) { //s="00ff00"
        flamingoBtn.tintColor = UIColor(netHex:num2) //this btn is an IBoutlet
     }

However, at some point I change the original image for another image (icon.png), programmatically, so I don't need to change the tint in this case, so far so good:

if let url = NSURL(string: "http://www.123di.com/CanonSGLens_132.png") {
            if let data = NSData(contentsOfURL: url) {
                var newImgThumb : UIImage=UIImage(data: data)!

                var iconBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
                iconBtn.setImage(newImgThumb, forState: UIControlState.Normal)
                iconBtn.addTarget(self, action: "goToSettings:", forControlEvents:  UIControlEvents.TouchUpInside)
                var item = UIBarButtonItem(customView: iconBtn)
                self.navigationItem.leftBarButtonItem = item
                print("CUSTOM ICON: DOWNLOADED")
            }
        }

The problem comes, when I switch to the icon image to the original silhouette.png, because I cannot modify the tint any longer, it remains always blue silhoute (default color), instead of green, red, etc:

        var newImgThumb : UIImage=UIImage(named: "happyface.png")!
        var replyBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
        replyBtn.setImage(newImgThumb, forState: UIControlState.Normal)
        replyBtn.addTarget(self, action: "goToSettings:", forControlEvents:  UIControlEvents.TouchUpInside)
        replyBtn.tintColor = UIColor.greenColor()
        var item = UIBarButtonItem(customView: replyBtn)
        item.tintColor = UIColor.greenColor()//UIColor(netHex:num2)
        self.navigationItem.leftBarButtonItem = item

What am I doing wrong, why are tint changes igonred afterwards?? If you need extra details let me know.

Yuchen
  • 30,852
  • 26
  • 164
  • 234
Josh
  • 6,251
  • 2
  • 46
  • 73
  • Have you tried storing a reference to the button and after it gets set and presented, changing the tint color at that point? – sschale Mar 22 '16 at 00:16

3 Answers3

4

If you google how to set the custom image for your bar button, pretty much everyone will tell you create a UIButton and then create the UIBarButtonItem from the UIButton as a customView:. In which case, you are doing the right thing here.

However, if you create the UIBarButtonItem via cutomView:, you are not able to change the tintColor any more. And this following is how you set custom image and also changing the tintColor

    let item = UIBarButtonItem.init(image: UIImage(named: "happyface.png")!,
                style: .Plain,
                target: self,
                action: Selector("goToSettings:"))
    item.tintColor = UIColor.greenColor()
    self.navigationItem.leftBarButtonItem = item

Depending where are you calling the code above, you might need to put it inside this structure, to make it run in the UI thread and make the change visible:

dispatch_async(dispatch_get_main_queue()) {  
//code here
}
Josh
  • 6,251
  • 2
  • 46
  • 73
Yuchen
  • 30,852
  • 26
  • 164
  • 234
  • Bro, you nailed it. Thanks!! I just had to wrap that code inside a dispatch_async(dispatch_get_main_queue()) { //code here } so that the code executes in the UI thread and the changes are visible. Just add that extra line of code and I will give you that green tick. @Yuchen-Zhong – Josh Mar 22 '16 at 15:42
  • Hey @Josh, glad to know that it helps :) I personally don't want to add the dispatching of queue in the answer here since it unrelated to the question that you were asking: **why I cannot change the tint colour**. Adding this will make the question/answer more complicated and less helpful to other people who has the same problem. And you should not add this if you know you are on UI thread and only dispatch when you are in background thread. Overall, dispatch_async is not cheap. – Yuchen Mar 22 '16 at 16:14
  • It makes sense, I have added it as an optional thing, since some people don't know about it and start thinking the code doesn't work. (me included, not long ago) @Yuchen-Zhong – Josh Mar 23 '16 at 08:59
1

In case someone is still looking for the solution.

barButtonItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: .normal)

By setting the NSAttributedString.Key.foregroundColor of the title text attributes, you can set the color of the button.

funclosure
  • 498
  • 6
  • 15
0

If you follow this way you can do whatever you need.

let logoutNavBarButtonItem = UIBarButtonItem.init(
    image: imageName,
    style: .plain,
    target: self,
    action: #selector(buttonPressed))
navigationItem.leftBarButtonItem = logoutNavBarButtonItem
Ferrakkem Bhuiyan
  • 2,741
  • 2
  • 22
  • 38