Xcode 4.5 background image iPhone 4, 4s, 5 - ios

I have in my viewController.m written the background code:
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"image.png"]];
And I have the correct names of the different pictures:
image.png for non-retina display (320x480)
image#2x.png for retina display (640x960)
image-568h#2x.png for iPhone 5 (640x1136)
But when I run it in the simulator it does not take the image-568h#2x.png for iPhone 5 screen it only takes the image#2x for 4s screen and scale it to fit the screen... I dont know if there is any coding to use the image-568h#2x for iPhone 5 screen?
Im using Xcode 4.5

iPhone 5 is retina, just like iPhone 4 and 4S, and the #2x-image will be used automatically for all these devices. It's only the startup-image that is called "-568h#2x" for iPhone 5. You need to write some code to use a different image, something like this would work:
NSString *filename = #"image.png";
CGRect screenRect = [[UIScreen mainScreen] bounds];
if (screenRect.size.height == 568.0f)
filename = [filename stringByReplacingOccurrencesOfString:#".png" withString:#"-568h.png"];
imageView.image = [UIImage imageNamed:filename];

if you are trying to use [UIImage imageNamed:#"image.png"] and expect image-568h#2x.png to be picked automatically from the bundle for iPhone 5, it will not work.
Automatic picking works only for iPhone 4 and 4S.
Only the Default image named as Default-568h#2x.png will be picked automatically in iPhone 5.
for normal images, if you have separate image for iPhone 5, try using this code
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
// code for 4-inch screen
} else {
// code for 3.5-inch screen
}

I believe it is incorrect to assume that you can apply the -568h#2x trick to all image files. I think it only works for Default-568h#2x.png. This is the file that iOS looks for at app launch on a 4" display device, as well as the "flag" to enable 4" display support in the SDK. For example, once you include this specific file, your table views will fill the screen.
I have not read anything to suggest that you can simply provide any image with the -568h#2x file name component and have it be used automagically. You'll have to do that yourself based on the screen size, e.g. [UIScreen mainScreen].bounds.size.height.

Related

Xcode asset catalog support for 3.5", 4", and 4.7" #2x images?

Xcode offers asset buckets for 1x, 2x, 4" 2x, and 3x assets. My fullscreen assets are all wonky with this configuration, because the 2x bucket is used for 3.5" and 4.7" screens. Currently I have a UIImage category that introspects the current screen size, and selects a "*-3.5" asset if the device seems to be 3.5".
This is clunky and not cool. Seeing that Xcode caters to all the different device sizes for their LaunchImage asset, I was hoping there was some way to supply device specific assets for non launch image assets without resorting to code.
I have reported a bug to Apple about this since mid November 2014 and I just noticed they marked it as No Value... which gives me the impression Apple has omitted an additional slot for iPhone 6 on purpose. My guess is they now want the 2x slot to be used for iPhone 6, and maybe they're reducing support to iPhone 4s as it's getting old.
If you really want to keep supporting the iPhone 4s, I'd suggest to use iPhone 6 sized images in the 2x slot, and then use the following method to load your images:
+(UIImage *)loadImageNamed:(NSString *)imageName
{
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGFloat screenHeight = MAX(screenSize.width, screenSize.height);
CGFloat const IPHONE_4_SCREEN_HEIGHT = 480;
UIImage *image = [UIImage imageNamed:imageName];
if(screenHeight == IPHONE_4_SCREEN_HEIGHT) {
CGFloat const xScale = .85333333;//x conversion ratio from iPhone 6's 375 pts width screen to iPhone 4's 320 pts width screen
CGFloat const yScale = .71964018;//y conversion ratio from iPhone 6's 667 pts height screen to iPhone 4's 480 pts height screen
CGSize newSize = CGSizeMake(xScale * image.size.width, yScale * image.size.height);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
[image drawInRect:(CGRect){0, 0, newSize}];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
return image;
}
Resizing a big image (iPhone 6) to a smaller one (iPhone 4) doesn't lose much quality even if the aspect ration is not the same.
Using an existing project when moving to Xcode 6 and iOS 8 creates some initial issues. I solved this by changing the image set from Device specific to Universal. This removes the R4 image option and leaves you with #1x, #2xand #3x. If you use for example a background image that needs to fit the screen then I will recommend that you find an image that does not have to fit 100 % perfect to look good, and set image to be displayed as Aspect Fill.
I have the same problem and got confirmation from apple that I have to wrote code for that. For example you can try like this Fullscreen images on iPhone 6 with Asset Catalogs
But I actually went lazy about it by using one 2x for 4" & 4.7" screen and another 2x for 3.5" screen

Background image to fit 3.5" and 4" screens

I have been looking online for a while now on how to make my images fit the iPhones 3.5" screen and 4" screen but i cant find anything.
I have a -568#2x.png image, a image.png, and a image#2x.png but when i run the simulator for the
iPhone 3.5" the image is stretched to far to the right.
I need help to fix this, please.
In terms of a Background image. Just add a UIImageView and which displays an image depending on screen size. (You will need to make two sets of images for this so you don't get any stretching).
You can then set which image to be displayed in the UIImageView by adding a simple if statement to check which screen size you have in the viewDidLoad method like this:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height == 480) {
// 3.5 inch display
[background_image setImage:[UIImage imageNamed:#"small_background.png"]];
}
else if (result.height == 568) {
// 4 inch display
[background_image setImage:[UIImage imageNamed:#"big_background.png"]];
}
}
Don't forget to declare "background_image" as a UIImageView in your header file:
IBOutlet UIImageView *background_image;

Should a universal app have 4 copies of each image?

In a universal app should I have a image.png, image#2x.png, image~ipad.png and image#2x~ipad.png for every image in my project?
Or should I just use my wider iPad images and have iOS scale them down to iPhone for me?
There's a lot of images so I'm a bit concerned about the file size...
Thanks!
Not necessarily but you can see code below. If you are targeting low res iPads and Low res iPhones you would have one set of icons for each. So if you are targeting iPad retina and iPhone retina that is on set of icons too so if you have an image called car.png and car#2x.png you would have 2 icons that cover all 4 models mentioned.
You can of course have images specific for iPad as the screen is larger then in your logic you would show either or depending on the device idiom..like below
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
//Device is iPhone
//This would give you low res icon for iPhone and if device is retina system will show it
UIImage *car = [UIImage imageNamed: #"Car.png"];
UIImageView *carImage = [[UIImageView alloc]initWithImage:car];
}
else {
//Device is iPad
//This would give you low res icon for iPad and if device is retina system will show it
UIImage *carLarge = [UIImage imageNamed: #"CarLarge.png"];
UIImageView *carImage = [[UIImageView alloc]initWithImage:carLarge];
}

iOS Image Naming Conventions

I'm relatively new in iOS development.
I'm currently building an app using the cocos2d library that will be available for the iPad Retina, iPad, iPhone 5, and iPhone 4s/4.
I'm getting all of my images setup, and I'm trying to figure out the naming conventions.
Does anyone know of a guide out there that could help me?
Say I have a background.png.
From what I understand:
background.png -> iPhone (non-retina/fallback)
background-hd.png -> iPhone 4s/4 (retina)
background-ipad.png -> iPad (non-retina)
background-ipadhd.png -> iPad (retina)
And the same naming convention would be used for all other files? For example:
arbitraryButton.png -> iPhone (non-retina/fallback)
arbitraryButton-hd.png -> iPhone 4s/4 (retina)
arbitraryButton-ipad.png -> iPad (non-retina)
arbitraryButton-ipadhd.png -> iPad (retina)
What do I name the iPhone 5 files?
I've searched a bit and cant seem to find any tangible guides out there on this.
Thank you!
The OS has a naming convention that you can use (and enforces for you, meaning you only need to reference the file as #"fileName"). The documentation is available here.
fileName.png -> iPhone (non-retina/fallback)
fileName#2x.png -> iPhone 4s/4 (retina)
fileName~ipad.png -> iPad (non-retina)
fileName#2x~ipad.png -> iPad (retina)
Note: ~iphone also exists, and can be used with/instead of using ~ipad. Using both ~ipad and ~iphone would safeguard against a third idiom Apple may introduce. cough TV cough
As for the iPhone 5, the OS does not enforce a naming scheme. But, it'd probably be wise to use the same scheme as that for the launch image.
fileName-568h#2x.png -> iPhone 5
To handle this easily throughout the app, you can create a category, and use it where you know you will have an iPhone 5 friendly image, as well as a regular sized image. A simple version can be made, like the one below.
UIImage+iPhone5Image.h
#import <UIKit/UIKit.h>
#interface UIImage (iPhone5Image)
+ (UIImage*)iPhone5ImageNamed:(NSString*)imageName;
#end
UIImage+iPhone5Image.m
#import "UIImage+iPhone5Image.h"
#define IsIPhone5() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568)
#implementation UIImage (iPhone5Image)
+ (UIImage*)iPhone5ImageNamed:(NSString*)imageName
{
if (IsIPhone5()) {
NSString* newImageName = [NSString stringWithFormat:#"%#-568h", imageName];
return [UIImage imageNamed:newImageName];
}
else {
return [UIImage imageNamed:imageName];
}
}
#end
It looks like you are after the cocos2d naming conventions not the standard UIKit versions. They are different and if you are using cocos2d you are recommended to use the cocos2d suffixes and not the UIKit ones.
They are as follows:
Non retina iPhone (No suffix)
Retina iPhone -hd
Non retina iPad -ipad
Retina iPad -ipadhd
iPhone 5 -iphone5 and -iphone5hd
All files that you want loaded based on the device that are used with the cocos2d methods can be suffixed like this.
Ok, Now cocos2d itself support iphone5.
-hd.png for iPhone HD
-ipad.png for iPad
-ipadhd.png for iPad HD
-wide.png for iphone 5
-widehd.png for iPhone 5 HD
If your Cocos2d version is old then use:
static inline NSString *i5res(NSString * data)
{
if(IS_IPHONE5)
{
return [data stringByReplacingOccurrencesOfString:#"." withString:#"-whd."];
}
return data;
}
//usage
CCSprite *bg = [CCSprite spriteWithFile:i5res(#"bg.png")];
For the compiler to automatically choose the right image you will want to name the standard (non-retina) images image.png and the retina images image#2x.png. Then in your code just refer to the standard one. The compiler will do the rest. So if you are setting an image it should look like this:
UIImage *anImage = [UIImage imageNamed:#"image.png"];
There isnt a specific naming convention for the iPhone 5, because the app won't automatically choose a different image size for the iPhone 5, you will have to do that in your code with something like this:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenHeight = screenRect.size.height;
if([[UIScreen mainScreen]bounds].size.height == 568){
UIImage *signUp = [UIImage imageNamed:#"signup-bg-568h.jpg"];
[signUpImage setImage:signUp];
}
else{
UIImage *signUp = [UIImage imageNamed:#"signup.jpg"];
[signUpImage setImage:signUp];
}

Migrate issues to iphone 5 resolution

I am using XCode 4.5.1 and iOS Simulator (Retina 4 inch)
I have project that I made one yera ago. So now I want to migrate my project to new resolution.
My problem is next:
I integrate code into my project to detect which resolution I have.
CGRect screenBounds = [[UIScreen mainScreen] bounds];
But after I out value of screenBounds to NSLog I got width = 320 and height = 480, but I exprected to see 1136 × 640.
Have you got the same issues?
Are you sure you are using the 4inch simulator? [[UIScreen mainScreen] bounds] will return the screen bounds in points, not pixels. So in the 4inch iPhone the CGRectreturned should be 320x568.
So if you call [[UIScreen mainScreen] bounds]:
<= iPhone 3GS: 320x480
iPhone 4 & iPhone 4S: 320x480
iPhone 5: 320x568
NOTE: If you didn't add the Default-568h#2x.png file, and the app runs letterboxed the method you used will return the iPhone 4 & 4S values.
TIP: To determine whether you are using an iPhone 5 or the rest, this code may come handy:
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
if( IS_IPHONE_5 )
{
// iPhone 5
}
else
{
// Other
}
To adapt your app to the new taller screen, the first thing you do is to change the launch image to: Default-568h#2x.png. Its size should be 1136x640 (HxW). Yep, having the default image in the new screen size is the key to let your app take the whole of new iPhone 5's screen.
Also, you'll have to take a few more steps:
Make sure, your Xibs/Views use auto-layout to resize themselves. Use springs and struts to resize views. If this is not good enough for your app, design your xib/storyboard for one specific screen size and reposition programmatically for the other.

Resources