I\'ve just upgraded to XCode 4.5 GM and found out that you can now apply the \'4\" Retina\' size to your view controller in the storyboard.
Now if I want to create a
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
// This is iPhone 5 screen
} else {
// This is iPhone 4 screen
}
First of all, you shouldn't rebuild all your views to fit a new screen, nor use different views for different screen sizes.
Use the auto-resizing capabilities of iOS, so your views can adjust, and adapt any screen size.
That's not very hard, read some documentation about that. It will save you a lot of time.
iOS 6 also offers new features about this.
Be sure to read the iOS 6 API changelog on Apple Developer website.
And check the new iOS 6 AutoLayout capabilities.
That said, if you really need to detect the iPhone 5, you can simply rely on the screen size.
[ [ UIScreen mainScreen ] bounds ].size.height
The iPhone 5's screen has a height of 568.
You can imagine a macro, to simplify all of this:
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
The use of fabs
with the epsilon is here to prevent precision errors, when comparing floating points, as pointed in the comments by H2CO3.
So from now on you can use it in standard if/else statements:
if( IS_IPHONE_5 )
{}
else
{}
Edit - Better detection
As stated by some people, this does only detect a widescreen, not an actual iPhone 5.
Next versions of the iPod touch will maybe also have such a screen, so we may use another set of macros.
Let's rename the original macro IS_WIDESCREEN
:
#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
And let's add model detection macros:
#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )
#define IS_IPOD ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPod touch" ] )
This way, we can ensure we have an iPhone model AND a widescreen, and we can redefine the IS_IPHONE_5
macro:
#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )
Also note that, as stated by @LearnCocos2D, this macros won't work if the application is not optimised for the iPhone 5 screen (missing the Default-568h@2x.png image), as the screen size will still be 320x480 in such a case.
I don't think this may be an issue, as I don't see why we would want to detect an iPhone 5 in a non-optimized app.
IMPORTANT - iOS 8 support
On iOS 8, the bounds
property of the UIScreen
class now reflects the device orientation.
So obviously, the previous code won't work out of the box.
In order to fix this, you can simply use the new nativeBounds
property, instead of bounds
, as it won't change with the orientation, and as it's based on a portrait-up mode.
Note that dimensions of nativeBounds
is measured in pixels, so for an iPhone 5 the height will be 1136 instead of 568.
If you're also targeting iOS 7 or lower, be sure to use feature detection, as calling nativeBounds
prior to iOS 8 will crash your app:
if( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] )
{
/* Detect using nativeBounds - iOS 8 and greater */
}
else
{
/* Detect using bounds - iOS 7 and lower */
}
You can adapt the previous macros the following way:
#define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_WIDESCREEN_IOS8 ( fabs( ( double )[ [ UIScreen mainScreen ] nativeBounds ].size.height - ( double )1136 ) < DBL_EPSILON )
#define IS_WIDESCREEN ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_WIDESCREEN_IOS8 : IS_WIDESCREEN_IOS7 )
And obviously, if you need to detect an iPhone 6 or 6 Plus, use the corresponding screen sizes.
CGFloat height = [UIScreen mainScreen].bounds.size.height;
NSLog(@"screen soze is %f",height);
if (height>550) {
// 4" screen-do some thing
}
else if (height<500) {
// 3.5 " screen- do some thing
}
this is the macro for my cocos2d project. should be the same for other apps.
#define WIDTH_IPAD 1024
#define WIDTH_IPHONE_5 568
#define WIDTH_IPHONE_4 480
#define HEIGHT_IPAD 768
#define HEIGHT_IPHONE 320
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//width is height!
#define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_5 )
#define IS_IPHONE_4 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_4 )
#define cp_ph4(__X__, __Y__) ccp(cx_ph4(__X__), cy_ph4(__Y__))
#define cx_ph4(__X__) (IS_IPAD ? (__X__ * WIDTH_IPAD / WIDTH_IPHONE_4) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPHONE_4) : (__X__)))
#define cy_ph4(__Y__) (IS_IPAD ? (__Y__ * HEIGHT_IPAD / HEIGHT_IPHONE) : (__Y__))
#define cp_pad(__X__, __Y__) ccp(cx_pad(__X__), cy_pad(__Y__))
#define cx_pad(__X__) (IS_IPAD ? (__X__) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPAD) : (__X__ * WIDTH_IPHONE_4 / WIDTH_IPAD)))
#define cy_pad(__Y__) (IS_IPAD ? (__Y__) : (__Y__ * HEIGHT_IPHONE / HEIGHT_IPAD))
I think it should be good if this macro will work in device and simulator, below are the solution.
#define IS_WIDESCREEN (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE (([[[UIDevice currentDevice] model] isEqualToString:@"iPhone"]) || ([[[UIDevice currentDevice] model] isEqualToString: @"iPhone Simulator"]))
#define IS_IPOD ([[[UIDevice currentDevice]model] isEqualToString:@"iPod touch"])
#define IS_IPHONE_5 ((IS_IPHONE || IS_IPOD) && IS_WIDESCREEN)
+(BOOL)isDeviceiPhone5
{
BOOL iPhone5 = FALSE;
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568)
{
// code for 4-inch screen
iPhone5 = TRUE;
}
else
{
iPhone5 = FALSE;
// code for 3.5-inch screen
}
return iPhone5;
}