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

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

我该怎么做呢?


当前回答

使用下列守则:

CGFloat screenScale = [[UIScreen mainScreen] scale];

CGRect screenBounds = [[UIScreen mainScreen] bounds]; 

CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale); 

if (screenSize.height==1136.000000)
{ 
    // Here iPhone 5 View

    // Eg: Nextview~iPhone5.Xib
} else {
   // Previous Phones 

   // Eg : Nextview.xib
}

其他回答

这是我们的代码,在ios7/ios8上测试通过,适用于iphone4、iphone5、ipad、iphone6、iphone6p,无论在设备上还是模拟器上:

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) // iPhone and       iPod touch style UI

#define IS_IPHONE_5_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
#define IS_IPHONE_6_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0f)
#define IS_IPHONE_6P_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height < 568.0f)

#define IS_IPHONE_5_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 568.0f)
#define IS_IPHONE_6_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 667.0f)
#define IS_IPHONE_6P_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) < 568.0f)

#define IS_IPHONE_5 ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_5_IOS8 : IS_IPHONE_5_IOS7 )
#define IS_IPHONE_6 ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_6_IOS8 : IS_IPHONE_6_IOS7 )
#define IS_IPHONE_6P ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_6P_IOS8 : IS_IPHONE_6P_IOS7 )
#define IS_IPHONE_4_AND_OLDER ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_4_AND_OLDER_IOS8 : IS_IPHONE_4_AND_OLDER_IOS7 )

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

使用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,使用相应的屏幕尺寸。

我冒昧地将Macmade的宏放入一个C函数中,并正确地命名它,因为它可以检测宽屏可用性,而不一定是iPhone 5。

如果项目不包含Default-568h@2x.png,宏也不会检测到在iPhone 5上运行。如果没有新的默认图像,iPhone 5将显示常规的480x320屏幕大小(以点数计算)。因此,检查不仅仅是宽屏可用性,而是宽屏模式是否启用。

BOOL isWidescreenEnabled()
{
    return (BOOL)(fabs((double)[UIScreen mainScreen].bounds.size.height - 
                                               (double)568) < DBL_EPSILON);
}

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

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

使用下列守则:

CGFloat screenScale = [[UIScreen mainScreen] scale];

CGRect screenBounds = [[UIScreen mainScreen] bounds]; 

CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale); 

if (screenSize.height==1136.000000)
{ 
    // Here iPhone 5 View

    // Eg: Nextview~iPhone5.Xib
} else {
   // Previous Phones 

   // Eg : Nextview.xib
}