如何检测 IOS 7 和 IOS 8 以及宽屏 iPhone 尺寸以使我的应用程序通用?

Posted

技术标签:

【中文标题】如何检测 IOS 7 和 IOS 8 以及宽屏 iPhone 尺寸以使我的应用程序通用?【英文标题】:How to detect IOS 7 and IOS 8 and widescreen iPhone sizes to make my app universal? 【发布时间】:2014-12-16 01:36:43 【问题描述】:

我正在为所有设备以及 ios 7 和 IOS 8 开发通用 IOS 应用程序。我有这个宏:

此宏用于检测宽屏 iPhone 5,适用于 IOS 7:

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

此宏也适用于宽屏 iPone 5,但仅适用于 IOS 8:

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

我需要结合此代码以使其同时在 IOS 7 和 IOS 8 上运行,为此我需要检测 IOS 版本的选择器。代码如下:

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

然后帖子的作者建议引用-“如果您还针对 iOS 7 或更低版本,请务必使用功能检测,因为在 iOS 8 之前调用 nativeBounds 会使您的应用程序崩溃:”并给出以下代码:

if( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] )

    /* Detect using nativeBounds - iOS 8 and greater */

else

    /* Detect using bounds - iOS 7 and lower */

请在这里帮助我,我是一名初学者开发人员,并希望了解使其工作。我应该把 SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"Background"]; 放在哪里?

所有这些代码都来自 *** 帖子中的不同帖子:How to detect iPhone 5 (widescreen devices)?

我上传图片到drop box这里是链接https://www.dropbox.com/sh/pnll2e2jvo0uigs/AACOLbzzQqZlJEZZcBx7TMR1a?dl=0这个文件夹叫做measuredImages。这是我用于添加背景的代码:#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;

如果有人可以将完整的代码与宏和用法放在答案中,我将不胜感激。

重要 更新:12.17.2014

正如 Daij-Djan 建议的那样,通过包含正确的启动图像和我的应用程序以正确的分辨率运行并且我使用了屏幕边界 [与 ios7 中相同],这个问题得到了解决。感谢所有尝试或帮助我解决此问题的人,我个人要感谢 Daij-Djan 和 sha 的帮助和支持。如果您需要宽屏 iphone 的代码,我会将其留在下面我自己的答案中,它可以在 iPhone 4 以上的所有 iPhone 和所有 iPad 上运行。

【问题讨论】:

为什么需要区分 iOS 7 和 iOS 8? 查看此链接:***.com/questions/7848766/… 致 rmaddy。我正在用 sprite kit 开发游戏,我已经完成了。我需要检测宽屏 iPhone 5,6。所以我的玩家在他们拥有的任何设备上都会有同样好的体验。我有适用于所有 IOS 设备的图像,并希望我的游戏能够针对所有设备以及 IOS 7 和 8 进行优化,因为大约 45% 的用户拥有 IOS 7,如果我不使其通用,我将失去这些玩家,而对于 IOS 7, 8 【参考方案1】:

当我需要一种快速而肮脏的方式来检测 iOS7/8 和 iPhone/iPad 设备时,我将使用以下宏:

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

你可以使用这些宏:

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
   ...

更新:要检测宽屏设备,您可以使用以下宏(因为 iOS8 UIScreen 会感知方向并且纵向/横向的高度会有所不同,因此您可以同时检查两者:

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

【讨论】:

但是你如何使用它呢?你能给我举个例子吗?例如:if(IS_IPONE) 好的,非常感谢,我会尝试一下,然后告诉你它是否有效,无论如何感谢回复!!! 不,它不起作用,可能代码有问题,但无论如何谢谢。 抱歉这不是你的错我的宏#define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) 当它崩溃时它会说什么?【参考方案2】:

使用这个非常有用

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

【讨论】:

#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) 【参考方案3】:

你不需要去特定的操作系统来检测屏幕宽度。

只需包含正确的启动图像,您的应用就会以正确的分辨率运行,并且您可以使用屏幕边界 [与 ios7 中相同]

我再次强调:包括正确的启动图像! 然后使用UIScreen bounds

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

【讨论】:

但有人说你需要以这种方式检查边界“nativeBounds”,因为边界不适用于 IOS 8,因为它使用像素而不是点,例如,IOS 7 为 568,IOS 8 为 1136 某人大错特错。 bounds 使用点并且完全适合。只需添加正确的启动图像,以便获得正确的边界(例如 iphone6 的 375) 它不适用于启动图像。它用于游戏中的背景图像。我需要它针对所有设备和 IOS 版本至少针对 7,8 进行优化。所以我有所有设备 Iphone 4 640x960、iPhone 5 640x1136 等的背景图片。我有 sprite kit 游戏的背景图片,我希望它出现在所有设备上 启动图片与他想要实现的目标无关。他需要在运行时检测屏幕尺寸。 对不起,你没明白。如果没有正确的启动图像,iOS 不会给你正确的界限。这就是它的全部内容【参考方案4】:

要检测 iOS 版本,您可以使用以下宏之一:

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

例子:

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

并且要检测 iPhone 类型,您可以使用,

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

【讨论】:

如果没有正确的启动图像,AFAICS 将无法正常工作,使其成为我的答案的欺骗 ;) -- 如果我错了,请纠正我 我应该在 images.xcassets 或 launchScreen.xib 中哪里添加 launchImages?【参考方案5】:

好的,因此解决此问题的方法是将正确的启动图像包含到 image.xcassets 或 LaunchImage.xib 中,编译器将为您的图像选择正确尺寸的屏幕,如上述答案中提到的 Daij-Djan。为了使其适用于宽屏 iPhone 和所有 iPhone(4,4s 及以上)和 iPad 以及 IOS 7 和 IOS 8。将此宏添加到您的 MyScene.m 文件或您使用它的任何 .m 文件中。

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

并使用此代码检测宽屏 iPhone,这适用于所有 IOS 设备以及 IOS 7 和 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;

最后一步是以这种方式命名您的图像:Background@2x.png for iPhone 4,4s, Background-568@2x 用于宽屏 iPhone 5,5c,5s,Background-667@2x.png 用于宽屏 iPhone 6,background@3x.png 用于 iPhone 6 Plus,Background~iPad.png 用于 iPad 常规显示,最后是 Background~iPad @2x.png 用于 iPad 视网膜显示屏。 您可以从 Dropbox 下载针对特定屏幕尺寸优化的图像。这是链接https://www.dropbox.com/sh/pnll2e2jvo0uigs/AACOLbzzQqZlJEZZcBx7TMR1a?dl=0 并尝试一下。最后也是最重要的事情是为每个屏幕尺寸添加启动图像,否则代码将不起作用。我希望这会有所帮助,并感谢你们教会了我这一切我失去了 2 个月的时间来让它工作,因为我有错误的信息。

【讨论】:

【参考方案6】:

它适用于 5c & 6 & 6plus。 它将检查屏幕是否为 16 : 9。 我是iOS新手,请指教

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;


【讨论】:

以上是关于如何检测 IOS 7 和 IOS 8 以及宽屏 iPhone 尺寸以使我的应用程序通用?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 11坑惨iPhone6/6S/7/8/X!苹果神回应

iOS 7 uinavigationcontroller 如何检测滑动?

Xcode 7 Stack Views 如何向后兼容 iOS 8 和 iOS 7?

我们如何在 iOS 7 上检测何时控制中心?

图文详解uni-app PC端宽屏适配方案

如何在 iOS 7 中检测水龙头的位置