Detecting iPhone6 & iPhone6 Plus using macros - ios

I am attempting to detect whether the current device is iPhone5, iPhone6 or iPhone 6 Plus.
In my app I am already using this macro to detect iPhone 5 which works perfectly.
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
Similarly, I use this macro to detect iPhone 6 and iPhone 6 Plus.
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)
The IS_IPHONE_5 macro works as expected in any orientation.
My problem is that the IS_IPHONE_6 and IS_IPHONE_6_PLUS macros do not return true when the device is held in LANDSCAPE. However they do work as expect while the device is held in PORTRAIT. What gives?
Also if anyone has a better recommendation to detect iPhone5, 6 and 6 Plus please share.

This is tested and designed for any combination of iOS system versions and SDK versions
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
Note: If iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. This is reflected in the macros.
Usage: http://pastie.org/9687735

Don't use the screen size for this, it's better to use the hardware model. We are getting more and more screen sizes every year, the less you hard-code screen dimensions in your code the better for your future self.
You need a helper function to get the machine name. I'm using dispatch_once to avoid querying the system multiple times for data that won't change.
NSString* machineName()
{
static NSString* name = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
struct utsname systemInfo;
uname(&systemInfo);
name = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
});
return name;
}
Then define a few macros as needed:
#define IS_IPHONE_6 [machineName() isEqualToString:#"iPhone7,2"]
#define IS_IPHONE_6_PLUS [machineName() isEqualToString:#"iPhone7,1"]
For some models is trickier:
#define IS_IPHONE_5s [machineName() hasPrefix:#"iPhone6,"]
Finally, use the macros in your code:
if (IS_IPHONE_6) {
// for the 6
}
Note: This answer your question (detect models with macros) but you're doing it wrong IMHO. You should use autolayout and size classes, unless you support really old iOS versions...

Take a look at this answer: iOS - How to get device make and model? it doesn't use macros but it does the job. I've seen some similar problems with macros to detect iPhone 6 and iPhone 6 plus. So it would be a better idea to try out the answer from #Ohhmee
EDIT: Of course there probably is a solution detecting it with macros. But I don't know that and I can't find a solution so i'm suggesting a different approach.

Your macros are ridiculous and seem to indicate a fear of floating-point arithmetic.
#define IS_IPHONE_5 ([UIScreen mainScreen].bounds.size.height == 568)
#define IS_IPHONE_6 ([UIScreen mainScreen].bounds.size.height == 667)
#define IS_IPHONE_6_PLUS ([UIScreen mainScreen].bounds.size.height == 736)
will work just as good (or just as bad). Most likely they will work just as bad.
If you are interested in features of the iPhone 6 or 6+, check for the features, not the screen size. It is quite likely that Apple will soon have a 4" phone with all the iPhone 6 features. Or a cheap 6c with a big screen but without iPhone 6 features.
For user interface and so on, just take the mainScreen bounds and lay out your views accordingly. At this point, hard coding for fixed sizes is absolutely ridiculous and will bite you. You should be able to run for example on a 12" iPad with a split screen without problems, and heavens knows what screen size that will be.

Related

Making an ui to be adaptable in various iOS devices

How to make my ui to be adaptable in all iOS devices.While researching , I saw few code where they've defined the sizes of various devices and designed the ui based on the size values. A sample code of how it is defines is as follows,
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
Its tedious, if I have to detect size each time. In case of android, there exists fragments to make ui work with various screen size. Is there any alternative for fragments in iOS and How to make my ui to be adaptable in various devices?
Hello I have one solution for you what i am using in my project.
I am using one simple mathematical equation to do this.
CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width*100/320, [UIScreen mainScreen].bounds.size.height*100/568);
Here i have one view and according to 5s i want it's size with (100x100) so i give that condition that will take size according to screen size increase or decrease.
In 5s it will take 100x100
In 6 it will take (375*100/320) Width and (667*100/568) Height
May be this will help you.

Check iPhone device version fails on device

I am trying to detect on which iPhone my app is running.
I found this, here at stackoverflow:
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
But this doesn't work for me. When I have an iPhone6 in standardmode (not zoomed) it says it is an iPhone5.
I also tested
[UIScreen mainScreen].bounds.size.width
but this returns everytime 320.
In simulator it works perfect but on device it fails.
Can someone help me to find out which iPhone is used?
best regards
Instead of relying on screen size, why not use "[[UIDevice curentDevice] model]" instead?
Here's a tutorial that might help you out.
And if "[[UIDevice currentDevice] model]" isn't detailed enough for you, there's also "sysctlbyname("hw.machine", machineNameAsCString, &size, NULL, 0);", where the tutorial shows how to get a "nice string" (or nice version of the model name) out of it.
There's also Open Source available that you can drop in to determine the Device display name.

From iPhone 5 to iPhone 6 and Plus, everything written in codes, solution proposed

I have a project which is supported for iPhone 5 and 4.
I wrote everything in code,i.e. no xibs or storyboards.
For example, a custom cell, there is a imageView like:
self.thumbnailImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 300, 180)];
In order to support 6 and plus, I want to scale the frame to fit 6 and plus screen, so I did something like:
self.thumbnailImageView = [[UIImageView alloc]initWithFrame:CGRectMake(CAL(10), CAL(10), CAL(300), CAL(180))];
Where CAL is a Marco:
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_5_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH <= 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define CAL(x) (IS_IPHONE_5_OR_LESS? x : RECAL(x) )
#define RECAL(x) (IS_IPHONE_6?RECAL_6(x):RECAL_6P(x))
#define RECAL_6(x) (x*375.0/320)
#define RECAL_6P(x) (x*414.0/320)
It checks if the device is 5/less or 6/plus and adjust the value accordingly.
I am not sure if this solution is feasible. I tried in simulator and it seemed working fine. Ang suggestions?
I also tried autoresizingMask, but it seems this method needs to change quite a lot of things and it is more complex.

xcode when i run program on iphone 5 screen looks iphone 4

I'm using Xcode 6 and use objective-c when i test program on iOS 8 (iPhone 5) program run without error but when i try to test program on iOS 7 (iPhone 5) screen look like iPhone 4 screen. I can detect phone like this;
#define iPhone6Plus ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 736)
#define iPhone6 ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 667)
#define IS_IPHONE_5 ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568)
#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
and also i can detect operating system like this;
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_0)
{
#define IS_IPHONE_5 ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568)
}
When i do this screen not scale on phone because when i run on iOS 7 phone screen run like iPhone 4 check image for more description.
As you can see top and bottom black.How can i fix this problem
Set an iPhone 5 launch screen. It will be fixed.
iPhone 5 launch screen spec: 640x1136
For the time being create a blank screen on photoshop or preview. You can replace it later.

Detect iPhone specific application 'is running' on iPAD

I have an app which is developed for iPhone only. When user runs it on iPAD
it is not showing properly. I know how to detect "IS_iPAD" when project is universal but
when project is iPhone specific the USER DEVICE is always returned as iPhone.
How one can detect if iPhone specific application is run on iPAD?
For sake of completion here is the #MichaelPatzer answer pointed by #user42949
If the app is an iPhone app running in the emulator mode on an iPad,
it will have a userInterfaceIdiom of Phone, but a model type of iPad.
You can check this with the following code:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
[[[UIDevice currentDevice] model] hasPrefix:#"iPad"]) {
// This app is an iPhone app running on an iPad
}
You can use this different macro to know if you are using iPhone, iPhone 5 or iPad :
#define IS_IPHONE() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPAD() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE5() ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) && [UIScreen mainScreen].bounds.size.height == 568)
Another option, if your code is layout-specific (which is how I got here):
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGFloat screenRatio = MIN(screenSize.width / screenSize.height, screenSize.height / screenSize.width); // account for rotation
if(screenRatio > 6.65 && screenRatio < 6.67) {
// iPad is 6.66666
}

Resources