UIBarButtonItem with UIImage Always Tinted iOS 7
Asked Answered
M

5

63

I'm trying to add a UIBarButtonItem containing a UIImage to a UIToolbar. The image keeps being tinted and I can't get it to show as the original colored image - all I want to do is display an image, verbatim, in a UIBarButtonItem! I'm following the directions in the iOS 7 transition guide to set the image rendering mode to UIImageRenderingModeAlwaysOriginal.

UIImage *image = [UIImage imageNamed:@"myImage.png"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

UIBarButtonItem *ratingImage = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleBordered target:nil action:nil];

[toolbar setItems:[NSArray arrayWithObjects:ratingImage, nil] animated:YES];

One thing to note is that I set the tintColor for the main UIWindow of my app right when it loads...maybe this isn't important with regard to my issue, but thought I'd mention it.

Muna answered 15/10, 2013 at 2:18 Comment(0)
L
173

I spent an evening trying to figure this out as well. You were very close to the solution. The trick is to instantiate the UIImage with the rendering mode.

Instead of doing:

 UIImage *image = [UIImage imageNamed:@"myImage.png"];
 image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

do this:

 UIImage *image = [[UIImage imageNamed:@"myImage.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

and it works!

In my case, I had dragged a Navigation bar to my viewcontroller in the IB, and added the BarButtonItem. But don't provide the item an image in the IB. Make an outlet and assign it the UIImage (like we created above) by doing this:

[myCustomBarButtonItem setImage:image];

Hope this works for you.

Latishalatitude answered 29/10, 2013 at 21:9 Comment(10)
I don't see how the two statements above differ. Given everything I know about objc they shouldn't! it's just the same statement compressed into one line and without a temporary variable assignment... What am I not getting here? Is there something fundamental about the language that I've gotten wrong or is it that I'm simply missing something?Fustanella
@Fustanella to be honest, that's exactly what I wasted my evening on. There doesn't seem to be any difference between the 2, but the latter works and the former does not. Could be a bug in the SDK.Latishalatitude
I agree with @entropy, that is some weird voodoo. I don't see how it could be a bug in the SDK. Could it be a side-effect of ARC?Boldface
By the way, it looks like imageWithRenderingMode: is only available in iOS 7... if you're targeting iOS 6 or below, you'll need something elseFeriga
I just experienced the same thing as @ScorpionKing2k5, in the iOS 8 GM. Crazy, but apparently still true.Devalue
Thanks for the super useful answer @ScorpionKing2k5, I come back to this one all the time. For others out there, it may be worthwhile to create a Category on UIImage for these purposes. Then you can do [UIImage originalImageNamed:@"myImage.png"], and the implementation returns [[UIImage imageNamed:@"myImage.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];Muna
Thank you for your post. That saved me a lot of time.Lavonlavona
Can this be achieved through storyboard?Aardvark
I cannot believe this sh*t D: This took me hours. Thank you so much :) It's still the same on Xcode 6.4/ iOS 8.4Contemporary
Is there is any other way ? Like special type of image which do not require setting UIImageRenderingModeAlwaysOriginal ?Be
S
11

UIImageRenderingModeAlwaysOriginal can also be set by selecting the image in your Assets.xcassets "folder" in XCode and setting the "Render as" dropdown to "Original image".

Siddons answered 6/2, 2016 at 13:54 Comment(0)
G
9

For Swift 2.1+ it would look like this:

let image : UIImage? = UIImage(named:"myImage.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)

UPDATED Swift 3

let image : UIImage? = UIImage(named:"myImage.png")!.withRenderingMode(.alwaysOriginal)
Guardsman answered 23/11, 2015 at 17:26 Comment(2)
Is there is any other way ? Like special type of image which do not require setting UIImageRenderingModeAlwaysOriginal ?Be
@Guardsman my friend, you saved my day!! That was EXACTLY what I've been searching for this whole afternoon. Thanks a lot!Apathetic
E
0

The accepted answer is fine but if you placed the UIBarButtonItem in a storyboard or xib then you can just:

  • Go to the Assets catalog where the image lives
  • Select the image
  • Go to the attributes inspector (cmd-opt-4)
  • Set "Render As" to "Original Image"

Only do this if you want all instances of this image to show up without tinting.

enter image description here

Egyptology answered 27/11, 2018 at 1:38 Comment(0)
F
-4

If you want it to work for versions of iOS less than v7, you might need to to this:

UIImage *image = [UIImage imageNamed:@"myImage.png"];
@try {
  image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
} @catch (NSException *exception) {
}

Since imageWithRenderingMode: is an iOS 7 method, you'll get an exception if you try and use it with a lesser version.

Feriga answered 29/3, 2014 at 21:27 Comment(2)
Don't use a try-catch block... instead check on this instead [image respondsToSelector:@selector(imageWithRenderingMode:)];Commutable
@Commutable is right - the above example is not the recommended way to call an API that might not be available. Use the respondsToSelector method.Muna

© 2022 - 2024 — McMap. All rights reserved.