Can I have a UIBarButtonItem with a colored image?

There is another way that does not involve coding at all.

First, place the images you want to put on the bar on the Assets.xcassets document.

Select the image on the assets browser.

Select the image

Open the Attributes inspector for that image on the right vertical toolbar.

Attributes inspector

On "Render As" select "Original Image".

Original Image

Even though on the storyboard the buttons will continue to be painted with the tint color, when running on the simulator the original image will be shown.

Simulator

The default rendering mode for an image varies from one UI control to the other. If you set this parameter on the attributes inspector, though, you can force that an image will be always represented with a specific rendering mode.

If you need the same image to be represented with different rendering modes on different controllers, then the response from MANIAK_dobrii is more appropriate.


There's other iOS7+ solution:

NSString *iconFilename = // ...
UIImage *image = 
    [[UIImage imageNamed:iconFilename] 
        imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIBarButtonItem *barButtonItem = 
    [[UIBarButtonItem alloc] initWithImage:image
                                     style:UIBarButtonItemStylePlain 
                                    target:self 
                                    action:@selector(onBarButtonItemTapped:)];

Swift 5:

let iconFilename: String = // ...
let image = UIImage(named: iconFilename)?.withRenderingMode(.alwaysOriginal)
let barButtonItem = UIBarButtonItem(image: image, 
                                    style: .plain, 
                                    target: self, 
                                    action: #selector(onBarButtonItemTapped(_:)))

Extract from UIImage.h:

... navigation bars, tab bars, toolbars, and segmented controls automatically treat their foreground images as templates ... You can use UIImageRenderingModeAlwaysTemplate to force your image to always be rendered as a template or UIImageRenderingModeAlwaysOriginal to force your image to always be rendered as an original.


In Swift 3:

let iconname = // ...
let image = UIImage(named: iconname)?.withRenderingMode(.alwaysOriginal)
let barButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(self. onBarButtonItemTapped))
self.navigationItem.leftBarButtonItem = barButtonItem

UPDATE: See MANIAK_dobrii's answer for an easier solution, available in iOS 7+.


Here is how I use an image for a UIBarButtonItem:

UIImage *image = [UIImage imageNamed:@"buttonImage.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.bounds = CGRectMake( 0, 0, image.size.width, image.size.height );    
[button setImage:image forState:UIControlStateNormal];
[button addTarget:myTarget action:@selector(myAction) forControlEvents:UIControlEventTouchUpInside];    
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
…