我刚刚升级到Xcode 4.5 GM,发现你现在可以将“4英寸视网膜”大小应用到故事板中的视图控制器上。
现在,如果我想创建一个同时在iPhone 4和5上运行的应用程序,当然我必须构建每个窗口两次,但我还必须检测用户的iPhone屏幕是3.5英寸还是4英寸,然后应用视图。
我该怎么做呢?
我刚刚升级到Xcode 4.5 GM,发现你现在可以将“4英寸视网膜”大小应用到故事板中的视图控制器上。
现在,如果我想创建一个同时在iPhone 4和5上运行的应用程序,当然我必须构建每个窗口两次,但我还必须检测用户的iPhone屏幕是3.5英寸还是4英寸,然后应用视图。
我该怎么做呢?
当前回答
用于检测所有版本的iPhone和iPad设备。
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)
其他回答
借用Samrat Mazumdar的回答,这里有一个估算设备屏幕大小的简单方法。它适用于最新的设备,但在未来的设备上可能会失败(正如所有猜测的方法一样)。如果设备正在镜像,它也会混淆(返回设备的屏幕大小,而不是镜像的屏幕大小)
#define SCREEN_SIZE_IPHONE_CLASSIC 3.5
#define SCREEN_SIZE_IPHONE_TALL 4.0
#define SCREEN_SIZE_IPAD_CLASSIC 9.7
+ (CGFloat)screenPhysicalSize
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height < 500)
return SCREEN_SIZE_IPHONE_CLASSIC; // iPhone 4S / 4th Gen iPod Touch or earlier
else
return SCREEN_SIZE_IPHONE_TALL; // iPhone 5
}
else
{
return SCREEN_SIZE_IPAD_CLASSIC; // iPad
}
}
这个问题已经得到了上百次的回答,但这个解决方案对我来说是最好的,并且在引入新设备时帮助解决了这个问题,而我没有定义一个大小。
Swift 5助手:
extension UIScreen {
func phoneSizeInInches() -> CGFloat {
switch (self.nativeBounds.size.height) {
case 960, 480:
return 3.5 //iPhone 4
case 1136:
return 4 //iPhone 5
case 1334:
return 4.7 //iPhone 6
case 2208:
return 5.5 //iPhone 6 Plus
case 2436:
return 5.8 //iPhone X
case 1792:
return 6.1 //iPhone XR
case 2688:
return 6.5 //iPhone XS Max
default:
let scale = self.scale
let ppi = scale * 163
let width = self.bounds.size.width * scale
let height = self.bounds.size.height * scale
let horizontal = width / ppi, vertical = height / ppi
let diagonal = sqrt(pow(horizontal, 2) + pow(vertical, 2))
return diagonal
}
}
}
这是因为记住手机的英寸大小很容易,比如“5.5英寸”或“4.7英寸”,但很难记住准确的像素大小。
if UIScreen.main.phoneSizeInInches() == 4 {
//do something with only 4 inch iPhones
}
这也给了你这样做的机会:
if UIScreen.main.phoneSizeInInches() < 5.5 {
//do something on all iPhones smaller than the plus
}
默认值:尝试使用屏幕大小和比例来尝试计算对角线英寸。这是为了防止出现一些新的设备大小,它将尽力确定和代码,如最后一个例子,应该仍然工作。
非常简单的解决方法
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
// iPhone Classic
}
if(result.height == 568)
{
// iPhone 5
}
}
在Swift, iOS 8+项目中,我喜欢在UIScreen上做一个扩展,比如:
extension UIScreen {
var isPhone4: Bool {
return self.nativeBounds.size.height == 960;
}
var isPhone5: Bool {
return self.nativeBounds.size.height == 1136;
}
var isPhone6: Bool {
return self.nativeBounds.size.height == 1334;
}
var isPhone6Plus: Bool {
return self.nativeBounds.size.height == 2208;
}
}
(注意:nativeBounds是以像素为单位)。
然后代码会是这样的:
if UIScreen.mainScreen().isPhone4 {
// do smth on the smallest screen
}
因此,代码清楚地表明这是对主屏幕的检查,而不是对设备模型的检查。
我冒昧地将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);
}