0

I am developing universal IOS app for all devices and IOS 7 and IOS 8. and I have this macros:

This macros is for detecting widescreen iPhone 5, this works for IOS 7:

#define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )

This macros is also for for widescreen iPone 5, but works only for IOS 8:

#define IS_WIDESCREEN_IOS8 ( fabs( ( double )[ [ UIScreen mainScreen ] nativeBounds ].size.height - ( double )1136 ) < DBL_EPSILON )

I need to combine this code to make it work on both IOS 7 and IOS 8and for that I need selector that detects IOS version., here is the code:

#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 )

then the author of the post suggests to quote -"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:" and gives following code:

if( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] )
{
    /* Detect using nativeBounds - iOS 8 and greater */
}
else
{
    /* Detect using bounds - iOS 7 and lower */
}

Please help me here I am a beginner developer and want to understand to to make it work. Where should I put SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"Background"];?

All this code is from different post in Stackoverflow post here is it: How to detect iPhone 5 (widescreen devices)?

I uploaded images to drop box here is the link https://www.dropbox.com/sh/pnll2e2jvo0uigs/AACOLbzzQqZlJEZZcBx7TMR1a?dl=0 the folder is called measuredImages. here is the code I use for adding background: #import "GameScene.h"

@implementation GameScene
-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"Background-568"]; background.anchorPoint = CGPointMake(0.5, 1);
        background.position = CGPointMake(self.size.width/2, self.size.height);
        [self addChild:background];}
    return self;
}

If someone could put full code with macros and usage in answer I would greatly appreciate it.

Important UPDATE:12.17.2014

This problem was solved by including the right launch images and my app run in the right resolution and I used screen bounds [same as in ios7], as Daij-Djan suggested. Thanks to everybody who tried or helped me to solve this problem,I personally want to thank Daij-Djan and sha for help and support. If you need the code for widescreen iphones I will leave it in my own answer below, it runs on all iPhones above iPhone 4 and all iPads.

Community
  • 1
  • 1
  • Why do you need to differentiate between iOS 7 and iOS 8? – rmaddy Dec 16 '14 at 02:32
  • 1
    check this link: http://stackoverflow.com/questions/7848766/how-can-we-programmatically-detect-which-ios-version-is-device-running-on – hahv Dec 16 '14 at 02:42
  • To rmaddy. I am developing game in sprite kit and I have it finished. I need to detect widescreen iPhone 5,6.So my players will have same good experience at any device they have. I have images for all IOS devices and want my game to be optimizes for al devices and also for IOS 7 and 8, because about 45% of users have IOS 7and I am loosing those players if I dont make it univeral and For IOS 7, 8 – David Muldarov Dec 16 '14 at 06:04

6 Answers6

2

When I need a quick and dirty way detecting iOS7/8 and iPhone/iPad device I will use the following macros:

#define IS_IOS8     ([[UIDevice currentDevice].systemVersion compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending)
#define IS_IPHONE   ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)

And you can use these macros:

if (IS_IPHONE) {
   // iPhone specific code
   ...
}
else {
   // iPad specific code 
   ...
}

if (IS_IOS8) {
   // Code specific to iOS8+
   ...
}
else {
   // Code specific to earlier versions of iOS
   ...
}

UPDATE: To detect wide screen devices you can use the following macro (since iOS8 UIScreen will be orientation aware and height will be different in portrait/landscape, so you can check for both:

#define IS_WIDESCREEN (( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON ) || ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.width - ( double )568 ) < DBL_EPSILON ))
sha
  • 17,824
  • 5
  • 63
  • 98
  • but how do you use it? Could you give me example? for example: if(IS_IPONE) { – David Muldarov Dec 16 '14 at 06:07
  • Ok thanks a lot I will try it and then tell you sha if it works or not thanks anyways for reply!!! – David Muldarov Dec 16 '14 at 07:12
  • No it doesnt work, may be there is some problem with code, but thanks anyway sha. – David Muldarov Dec 16 '14 at 08:34
  • Sorry it is not your fault my macro #define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON ) stopped working. It doesnt even work when I put it separately for IOS 7. I was working fine for ios 7 - now it is crashing – David Muldarov Dec 16 '14 at 22:08
  • What does it say when it's crashing? – sha Dec 16 '14 at 22:11
  • It doesnt crush this time but image is from iPhone 4s instead of iPhone 5 See edits in my original question above also image is there. – David Muldarov Dec 16 '14 at 22:34
  • That is expected :) Since iOS8 UIScreen class is orientation aware, so the height will be different in landscape. For iOS8 you should check width and height both – sha Dec 16 '14 at 22:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67063/discussion-between-david-muldarov-and-sha). – David Muldarov Dec 16 '14 at 22:46
  • he needs to detect the screen size and I kinda miss this in this answer – Daij-Djan Dec 16 '14 at 23:07
  • @Daij-Djan: Yeah, we figured this out in chat. I updated the answer with fixed macro for widescreen devices. – sha Dec 16 '14 at 23:31
  • And it only checks for iphone5 - which he had covered, no?! – Daij-Djan Dec 16 '14 at 23:48
  • It check for iphone 5 and it doesnt work for both IOS 7 and 8 – David Muldarov Dec 17 '14 at 01:22
  • Can you please update your question and specify _exactly_ what you need to detect? wide iPhone vs non-wide? iPhone 5 vs 6 vs 4 vs 6+ or vs iPad? Right now it's not clear and title gives very wrong impression – sha Dec 17 '14 at 02:41
  • Ok sha thanks for your help, the solvation was found, I needed to add launch images. didnt need to check for nativeBounds. Your help is much appreciated thanks again. – David Muldarov Dec 17 '14 at 22:41
2

Use This is Very useful

#define IS_IPHONE       ((int)(MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)) == 480)
#define IS_IPHONE5      ((int)(MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)) == 568)
#define IS_IPHONE6      ((int)(MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)) == 667)
#define IS_IPHONE6PLUS  ((int)(MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)) == 736)
sha
  • 17,824
  • 5
  • 63
  • 98
Rahul
  • 77
  • 4
  • What is the difference between #define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON ) and #define IS_IPHONE5 ((int)(MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)) == 568) ? – David Muldarov Dec 17 '14 at 22:24
1

To detect iOS versions you can use one of the following macros :

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

Example:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
    // code here
}

And to detect iPhone types, you can use,

CGSize applicationFrameSize = [UIScreen mainScreen].bounds.size;
CGFloat maxHeight = (MAX(applicationFrameSize.width, applicationFrameSize.height));
_is4GDevice = (maxHeight == 480.0 || maxHeight == 480.0);
_is5GDevice = (maxHeight == 568.0 || maxHeight == 568.0);
_is6GDevice = (maxHeight == 667.0 || maxHeight == 667.0);
_is6PlusDevice = (maxHeight == 736.0 || maxHeight == 736.0);
christijk
  • 1,753
  • 18
  • 26
1

you don't need to go os specific for detecting the screen width.

just include the right launch images and your app will run in the right resolution and you can just use the screen bounds [same as in ios7]

I stress again: include right launch images! THEN use the UIScreen bounds

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/LaunchImages.html

Community
  • 1
  • 1
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
  • but someone say you need to check bounds this way "nativeBounds" since bound doesnt work for IOS 8 because it uses pixels not points for example, 568 for IOS 7 and 1136 for IOS 8 – David Muldarov Dec 16 '14 at 22:13
  • 1
    that someone was dead-wrong. bounds uses points and is totally suited. just add the right launch images so you get the right bounds (e.g. 375 for iphone6) – Daij-Djan Dec 16 '14 at 23:03
  • It is not for launch images. It is for background image in the game. I need it to be optimizes for all devices and IOS versions at least for 7,8. So I have background images for all devices Iphone 4 640x960, iPhone 5 640x1136 and so on. I have backgrounds images for the sprite kit game and I want it to appear on all devices – David Muldarov Dec 16 '14 at 23:45
  • Launch images has nothing to do with what's he is trying to achieve. He needs to detect screen size in run-time. – sha Dec 16 '14 at 23:49
  • Sorry you don't get it. iOS won't give you right bounds without right launch images. That's all there is to it – Daij-Djan Dec 16 '14 at 23:50
  • I understand that unless you specify properly launch image (or launch XIB file) your app will get same resolution as iPhone 5 when running under iPhone 6/6+. But that's not the point. To include proper launch images is not enough - he needs to detect something in run-time, and it's actually not clear what exactly he is trying to detect. – sha Dec 17 '14 at 02:43
  • I am trying to detect all iphone and ipad screens for IOS 7 and 8, including widescreens (568,667, and so on) – David Muldarov Dec 17 '14 at 06:27
  • he wants the bounds -- and thats correctly set when including launch images – Daij-Djan Dec 17 '14 at 09:59
  • Yes my friend Daij-Djan you win:). This is a correct answerI will edit update my question and post the answer there. I added launch images to my project and it works flawlessly. All background images load in device's screens. Thanks a lot for your help, I marked your answer "answered" but for some reason cant up-vote it. it says I already voded. Thanks again for solving this problem and yes they were damn wrong when they say I need to check nativeBounds for IOS 8. – David Muldarov Dec 17 '14 at 22:36
  • glad I could help - was a hard way :D - You didn't mark it as answered though (There is no green tick mark here but on another answer) – Daij-Djan Dec 17 '14 at 23:16
  • Daij-Djan I did now.It is marked as answered!The thing is I thought I can mark answered the answers that I think helped me, but turns out you can mark answered only one answer so I choose yours :). Took me about 2 months to do simple thing because I had wrong info form this post http://stackoverflow.com/questions/12446990/how-to-detect-iphone-5-widescreen-devices answer of blogger named "Macmade", the one that has "green" answered mark (407 upvoted). he said to use nativeBounds for IOS 8. I dont have 50 votes to leave comment-you could leave comment proving he is wrong. Thanks again Daij-Djan – David Muldarov Dec 19 '14 at 00:55
1

Ok so the salvation to this problem is to include right launch images to image.xcassets or LaunchImage.xib and compiler will pick right size screen for your images as Daij-Djan mentioned in above answer. To make it work for widescreen iPhones and all iPhones (4,4s and above) and iPads and IOS 7 and IOS 8. add this macros your MyScene.m file or just any .m file where you use it.

 #define IS_WIDESCREEN_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_WIDESCREEN_6 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )667 ) < DBL_EPSILON )

and use this code for detecting widescreen iPhones, this works for all IOS devices and IOS 7 and IOS 8:

   -(id)initWithSize:(CGSize)size {

    if (self = [super initWithSize:size]) {
        SKSpriteNode *background;
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
            if (IS_WIDESCREEN_5) {
                //detects WIDESCREEN iPhone 5,5c,5s for both IOS 7,8
            background= [SKSpriteNode spriteNodeWithImageNamed:@"Background-568"];
            }else if (IS_WIDESCREEN_6){
                //detects WIDESCREEN iPhone 6 for both IOS 7,8
            background= [SKSpriteNode spriteNodeWithImageNamed:@"Background-667"];

            }else{
                //detects iPhone 4,4s,iPhone 6 Plus, for both IOS 7,8
            background= [SKSpriteNode spriteNodeWithImageNamed:@"Background"];
            }
        }else{
            //detects iPads all sizes and resolutions (Ipad regular display and iPad retina display)
             background= [SKSpriteNode spriteNodeWithImageNamed:@"Background~iPad"];
        }

    background.anchorPoint = CGPointMake(0.5, 1);
    background.position = CGPointMake(self.size.width/2, self.size.height);
    [self addChild:background];

    }
    return self;
}

And last step is name you images this way: Background@2x.png for iPhone 4,4s, Background-568@2x for widescreen iPhone 5,5c,5s, Background-667@2x.png for widescreen iPhone 6, background@3x.png for iPhone 6 Plus, Background~iPad.png for iPad regular display and lastly Background~iPad@2x.png for iPad Retina Display. You can download this images optimized for specific screen sizes from dropbox. Here is the link https://www.dropbox.com/sh/pnll2e2jvo0uigs/AACOLbzzQqZlJEZZcBx7TMR1a?dl=0 and try it. Last and most important thing is to add launch Images for each screen size otherwise the code will not work. I hope this helps and thanks for you guys who teach me all this I lost 2 months to get it work because I had wrong info.

1

It works on 5c & 6 & 6plus. It will check whether the screen is 16 : 9. I am a new iOS programmer, please advise

bool IsTargetDeviceWideScreen()
{
    double screenWidth  = 0;
    double screenHeight = 0;
    if ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) {
        CGSize screenSize = [ [ UIScreen mainScreen ] nativeBounds ].size;
        screenWidth       = screenSize.width;
        screenHeight      = screenSize.height;
    }
    else
    {
        CGSize screenSize = [ [ UIScreen mainScreen ] bounds ].size;
        screenWidth       = screenSize.width;
        screenHeight      = screenSize.height;
    }
    NSLog(@"screen size");
    NSLog(@"%f", screenWidth);
    NSLog(@"%f", screenHeight);
    double rateWidthHeight = 0;
    if (screenWidth < screenHeight) {
        rateWidthHeight = (screenWidth * 16) / (screenHeight * 9);
    }
    else
    {
        rateWidthHeight = (screenWidth * 9) / (screenHeight * 16);
    }
    NSLog(@"%f", rateWidthHeight);
    if ( 0.99 < rateWidthHeight & rateWidthHeight < 1.01) {
        return true;
    }
    return false;

}
Kevin John
  • 11
  • 2