我刚刚升级到Xcode 4.5 GM,发现你现在可以将“4英寸视网膜”大小应用到故事板中的视图控制器上。

现在,如果我想创建一个同时在iPhone 4和5上运行的应用程序,当然我必须构建每个窗口两次,但我还必须检测用户的iPhone屏幕是3.5英寸还是4英寸,然后应用视图。

我该怎么做呢?


当前回答

首先,您不应该重新构建所有视图以适应新屏幕,也不应该针对不同的屏幕大小使用不同的视图。

使用iOS的自动调整大小功能,这样你的视图就可以调整,并适应任何屏幕大小。

这并不难,阅读一些相关的文档。这会节省你很多时间。

iOS 6也提供了相关的新功能。 请务必阅读苹果开发者网站上的iOS 6 API更新日志。 检查新的iOS 6自动布局功能。

也就是说,如果你真的需要检测iPhone 5,你可以简单地依靠屏幕大小。

[ [ UIScreen mainScreen ] bounds ].size.height

iPhone 5的屏幕高度为568。 你可以想象一个宏,来简化这一切:

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

在比较浮点数时,使用带有epsilon的晶圆厂是为了防止精度错误,正如H2CO3在评论中指出的那样。

所以从现在开始,你可以在标准的if/else语句中使用它:

if( IS_IPHONE_5 )
{}
else
{}

编辑-更好的检测

正如一些人所说,这只检测到宽屏,而不是真正的iPhone 5。

下一个版本的iPod touch可能也会有这样的屏幕,所以我们可以使用另一组宏。

让我们重命名原始宏is_宽屏:

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

让我们添加模型检测宏:

#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )
#define IS_IPOD   ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPod touch" ] )

这样,我们可以确保我们有一个iPhone模型和一个宽屏,我们可以重新定义IS_IPHONE_5宏:

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

还要注意,正如@LearnCocos2D所述,如果应用程序没有针对iPhone 5屏幕进行优化(缺少Default-568h@2x.png图像),这个宏将无法工作,因为在这种情况下,屏幕大小仍然是320x480。

我不认为这是一个问题,因为我不明白为什么我们要在一个未优化的应用程序中检测到iPhone 5。

重要- iOS 8支持

在iOS 8中,UIScreen类的bounds属性现在反映了设备方向。 显然,前面的代码不能开箱即用。

为了解决这个问题,你可以简单地使用新的nativeBounds属性,而不是bounds,因为它不会随着方向而改变,而且它是基于肖像向上模式的。 注意,nativeBounds的尺寸是以像素为单位测量的,因此对于iPhone 5,高度将是1136而不是568。

如果你的目标是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 */
}

你可以采用以下方式调整前面的宏:

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

显然,如果你需要检测iPhone 6或6 Plus,使用相应的屏幕尺寸。

其他回答

我发现答案并不包括模拟器的特殊情况。

#define IS_WIDESCREEN ( [ [ UIScreen mainScreen ] bounds ].size.height == 568  )
#define IS_IPHONE ([[ [ UIDevice currentDevice ] model ] rangeOfString:@"iPhone"].location != NSNotFound)
#define IS_IPAD ([[ [ UIDevice currentDevice ] model ] rangeOfString:@"iPad"].location != NSNotFound)
#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

我们现在需要考虑iPhone 6和6Plus的屏幕尺寸。以下是最新的答案

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    //its iPhone. Find out which one?

    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    else if(result.height == 568)
    {
        // iPhone 5
    }
    else if(result.height == 667)
    {
        // iPhone 6
    }
   else if(result.height == 736)
    {
        // iPhone 6 Plus
    }
}
else
{
     //its iPad
}

一些有用的信息

iPhone 6 Plus   736x414 points  2208x1242 pixels    3x scale    1920x1080 physical pixels   401 physical ppi    5.5"
iPhone 6        667x375 points  1334x750 pixels     2x scale    1334x750 physical pixels    326 physical ppi    4.7"
iPhone 5        568x320 points  1136x640 pixels     2x scale    1136x640 physical pixels    326 physical ppi    4.0"
iPhone 4        480x320 points  960x640 pixels      2x scale    960x640 physical pixels     326 physical ppi    3.5"
iPhone 3GS      480x320 points  480x320 pixels      1x scale    480x320 physical pixels     163 physical ppi    3.5"

非常简单的解决方法

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    if(result.height == 568)
    {
        // iPhone 5
    }
}

我用hfossli的答案翻译给了Swift

let IS_IPAD = UIDevice.currentDevice().userInterfaceIdiom == .Pad
let IS_IPHONE = UIDevice.currentDevice().userInterfaceIdiom == .Phone
let IS_RETINA = UIScreen.mainScreen().scale >= 2.0

let SCREEN_WIDTH = UIScreen.mainScreen().bounds.size.width
let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
let SCREEN_MAX_LENGTH = max(SCREEN_WIDTH, SCREEN_HEIGHT)
let SCREEN_MIN_LENGTH = min(SCREEN_WIDTH, SCREEN_HEIGHT)

let IS_IPHONE_4_OR_LESS = (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
let IS_IPHONE_5 = (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
let IS_IPHONE_6 = (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
let IS_IPHONE_6P = (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
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

     }