views:

697

answers:

5

I place a play.png image onto my view. When the view initially loads, the iPhone 4 grabs the corresponding [email protected] file and it looks great. However, when I tap the play button my code swaps it out for the pause.png file. Then, when I tap the pause.png to bring back the play.png it uses the original play.png file (not the @2x version like I thought it would automatically reference).

This is the code I tried to use:

[button setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];

So, if I swap files after the initial view load, do I have to manually specify the @2x version inside an IF statement? If so, is the UIScreen.scale the best attribute to use for this?

I'm currently using code like this:

if ([UIScreen mainScreen].scale > 1.0) 
{ 
    [button setImage:[UIImage imageNamed:@"[email protected]"] forState:UIControlStateNormal]; 
} 
else 
{ 
    [button setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal]; 
}

It's working fine but having the IF statement in there is annoying and seems a little fragile.

Thanks in advance to all you smarties out there.

+4  A: 

The conditional statement is unnecessary. The following line is sufficient:

[button setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];

In iOS 4.0, the imageNamed: method automatically looks for the "@2x" filename suffix if the device is an iPhone 4 and has the retina display. In previous versions of iPhone OS, the imageNamed: method only looks for what you write (i.e., the lower-resolution image). This works because the iPhone 4 can't have a lower OS version then 4.0, so your retina display users will always have the higher resolution artwork.

Arseniy Banayev
You'll notice from my initial post that the line of code you gave me is exactly what I was using. It initially loaded the retina version of the play icon, but when I tapped it and swapped it with pause.png then back to play.png it would then use the low-res version of play.png.
Unfortunately, the code you're describing should work fine, so I think the problem is somewhere else in your project. I just made a button with two images and on each click it switches; works fine. Could you post all the code involving this button?
Arseniy Banayev
+1  A: 

Someone on another thread mentioned that they managed to solve a similarly vexing problem by deleting and re-adding their hi-res images to the project.

Tim K
+1  A: 

I ran into the same problem, then realized that my Windows Photoshop-exported .png files were .PNG files. Apparently the capitalization does matter.

Also see http://stackoverflow.com/questions/3340465/hi-res-2x-image-not-being-picked-up-for-tab-bar-item

amdfan
A: 

Two silly mistakes (both of which I've made before) that can cause this problem:

  1. Accidentally naming the small versions @2x instead of the large ones
  2. Having the large versions be slightly missized (by one pixel)
Jon Rodriguez
A: 

You can use just:

[UIImage imageNamed:@"play"]

Without the extension. This will load the @2x version if available and if the device has a x2 scale.

This will work for iOS4 or grater. However if you want to run your application in previous versions you could do the following:

UIImage* image = [UIImage imageNamed:@"play"]; // for iOS 4 or greater
if(!image)
    image = [UIImage imageNamed:@"play.png"]; // for previous iOS versions

The benefit is that this will work if at any moment you have @3x or any other version if Apple creates new devices or displays.

You can create an utility method to avoid doing this everywhere you need to load an image.

See: Supporting High-Resolution Screens, section "Loading Images into Your Application"

gimenete