如何检测iPhone 5(宽屏设备)?

Fin*_*ida 301 iphone screen objective-c device ios

我刚刚升级到XCode 4.5 GM,发现你现在可以将"4"Retina'大小应用到故事板中的视图控制器.

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

我该怎么办?

Mac*_*ade 468

首先,您不应重建所有视图以适应新屏幕,也不应对不同屏幕尺寸使用不同视图.

使用iOS 的自动调整大小功能,以便您的视图可以调整,并适应任何屏幕大小.

这不是很难,请阅读一些相关的文档.它会为你节省很多时间.

iOS 6还提供了相关的新功能,但目前仍在NDA下.如果您可以访问它,
请务必阅读Apple Developer网站上的API更新日志.

编辑:由于iOS 6现已用完,请检查新的AutoLayout功能.

也就是说,如果你真的需要检测iPhone 5,你可以简单地依赖屏幕尺寸.

[ [ UIScreen mainScreen ] bounds ].size.height
Run Code Online (Sandbox Code Playgroud)

iPhone 5的屏幕高度为568.
您可以想象一个宏,以简化所有这些:

#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
Run Code Online (Sandbox Code Playgroud)

fabsH2CO3的评论中所指出的,在比较浮点时,使用epsilon可以防止精度错误.

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

if( IS_IPHONE_5 )
{}
else
{}
Run Code Online (Sandbox Code Playgroud)

编辑 - 更好的检测

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

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

让我们重命名原始宏IS_WIDESCREEN:

#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
Run Code Online (Sandbox Code Playgroud)

让我们添加模型检测宏:

#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )
#define IS_IPOD   ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPod touch" ] )
Run Code Online (Sandbox Code Playgroud)

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

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )
Run Code Online (Sandbox Code Playgroud)

另请注意,正如@ LearnCocos2D所述,如果应用程序未针对iPhone 5屏幕进行优化(缺少Default-568h@2x.png图像),则此宏将无法工作,因为屏幕大小仍为320x480一件事.

我不认为这可能是一个问题,因为我不明白为什么我们想要在非优化的应用程序中检测iPhone 5.

重要信息 - iOS 8支持

在iOS 8上,类的bounds属性UIScreen现在反映了设备方向.
很明显,以前的代码不会开箱即用.

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

如果您还要定位iOS 7或更低版​​本,请务必使用功能检测,因为nativeBounds在iOS 8之前调用会导致您的应用崩溃:

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

您可以通过以下方式调整以前的宏:

#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 )
Run Code Online (Sandbox Code Playgroud)

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

最后的说明

意见和建议已纳入本文.
感谢大家.

  • 这个答案很疯狂.关于推荐不比较这些特定类型的浮点数(实际上是 - 如果你知道Apple应该知道它总是将 - 整数)与==的东西是无意义的并且使事情过于复杂.此外,我认为最好使用UI_USER_INTERFACE_IDIOM()进行iPhone检测,因为它在设备和模拟器上都能正常工作(并且它可能比UIDevice方法更快).这只是工作正常并且更容易阅读:#define IS_IPHONE5(UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone && [UIScreen mainScreen] .bounds.size.height == 568) (31认同)
  • @ H2CO3:注意比较`DBL_EPSILON`在这里没有必要,那``==比较将****不是失败,而是只需要使用不同这样,如果浮点值不能做对比以精确数字表示(例如"1.0/3.0*3.0").阅读[本文](http://www.mikeash.com/pyblog/friday-qa-2011-01-04-practical-floating-point.html)了解更多信息;) (28认同)
  • 这是错误的,你必须使用`#define IS_IPHONE_5([[UIScreen mainScreen] bounds] .size.height == 568)` (7认同)
  • 我要补充:如果你想这与模拟器使用此工作:#定义IS_IPHONE(([[[的UIDevice currentDevice]模型] isEqualToString:@ "iPhone"])||([[[的UIDevice currentDevice]模型] isEqualToString: @"iPhone模拟器"])) (5认同)
  • 这个答案不正确.为什么会这么多竖起大拇指?你不能只使用高度来确定它是否是宽屏.猪头... (2认同)
  • 其他一些答案比这个答案中使用的所有东西都更有效率和优雅.我在应用程序商店中有几个应用程序正在使用其他答案中的技术,它们都运行良好,它更简单,更清晰的代码. (2认同)

hfo*_*sli 233

针对SDK和OS的任何组合进行测试和设计:

迅速

添加了iPad类型.iPad 2和iPad mini是非视网膜iPad.iPad Mini 2及以上,iPad 3,iPad Air,Air 2,Air 3和iPad Pro 9.7具有相同的1024逻辑分辨率.iPad Pro的maxLength为1366. 参考

import UIKit

public enum DisplayType {
    case unknown
    case iphone4
    case iphone5
    case iphone6
    case iphone6plus
    case iPadNonRetina
    case iPad
    case iPadProBig
    static let iphone7 = iphone6
    static let iphone7plus = iphone6plus
}

public final class Display {
    class var width:CGFloat { return UIScreen.main.bounds.size.width }
    class var height:CGFloat { return UIScreen.main.bounds.size.height }
    class var maxLength:CGFloat { return max(width, height) }
    class var minLength:CGFloat { return min(width, height) }
    class var zoomed:Bool { return UIScreen.main.nativeScale >= UIScreen.main.scale }
    class var retina:Bool { return UIScreen.main.scale >= 2.0 }
    class var phone:Bool { return UIDevice.current.userInterfaceIdiom == .phone }
    class var pad:Bool { return UIDevice.current.userInterfaceIdiom == .pad }
    class var carplay:Bool { return UIDevice.current.userInterfaceIdiom == .carPlay }
    class var tv:Bool { return UIDevice.current.userInterfaceIdiom == .tv }
    class var typeIsLike:DisplayType {
        if phone && maxLength < 568 {
            return .iphone4
        }
        else if phone && maxLength == 568 {
                return .iphone5
        }
        else if phone && maxLength == 667 {
            return .iphone6
        }
        else if phone && maxLength == 736 {
            return .iphone6plus
        }
        else if pad && !retina {
            return .iPadNonRetina
        }
        else if pad && retina && maxLength == 1024 {
            return .iPad
        }
        else if pad && maxLength == 1366 {
            return .iPadProBig
        }
        return .unknown
    }
}
Run Code Online (Sandbox Code Playgroud)

在操作中查看它 https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

注意:如果例如iPhone 6处于缩放模式,则UI是iPhone 5的放大版本.这些功能不是确定设备类型,而是显示模式因此iPhone 5是此示例中的期望结果.

Objective-C的

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)

#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_ZOOMED (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)

#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
Run Code Online (Sandbox Code Playgroud)

用法:http://pastie.org/9687735

注意:如果例如iPhone 6处于缩放模式,则UI是iPhone 5的放大版本.这些功能不是确定设备类型,而是显示模式因此iPhone 5是此示例中的期望结果.

  • 一个可能有用的补充是`#define IS_RETINA([[UIScreen mainScreen] scale] == 2.0)`这将有助于确定iPhone4和iPhone5以及iPad Retina和非视网膜之间的差异 (3认同)

Sam*_*dar 69

真的很简单的解决方案

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

  • 好吧,不把东西放在宏观或功能上是不容易干的...从你需要做的这一刻起不止一次检查... (2认同)

Sam*_*m B 28

我们现在需要考虑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
}
Run Code Online (Sandbox Code Playgroud)

一些有用的信息

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"
Run Code Online (Sandbox Code Playgroud)


Lea*_*s2D 15

我冒昧通过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);
}
Run Code Online (Sandbox Code Playgroud)

  • 与性能相关的问题是,为什么在渲染循环期间会运行此检查数千次?否则,绩效不是问题和清晰,而是避免更重要的副作用. (4认同)

Gin*_*ger 11

这是我们的代码,测试通过ios7/ios8 for 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 )
Run Code Online (Sandbox Code Playgroud)


小智 7

我使用了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)
Run Code Online (Sandbox Code Playgroud)


OMG*_*POP 6

这是我的cocos2d项目的宏.对于其他应用应该是相同的.

#define WIDTH_IPAD 1024
#define WIDTH_IPHONE_5 568
#define WIDTH_IPHONE_4 480
#define HEIGHT_IPAD 768
#define HEIGHT_IPHONE 320

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)

//width is height!
#define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_5 )
#define IS_IPHONE_4 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_4 )

#define cp_ph4(__X__, __Y__) ccp(cx_ph4(__X__), cy_ph4(__Y__))
#define cx_ph4(__X__) (IS_IPAD ? (__X__ * WIDTH_IPAD / WIDTH_IPHONE_4) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPHONE_4) : (__X__)))
#define cy_ph4(__Y__) (IS_IPAD ? (__Y__ * HEIGHT_IPAD / HEIGHT_IPHONE) : (__Y__))

#define cp_pad(__X__, __Y__) ccp(cx_pad(__X__), cy_pad(__Y__))
#define cx_pad(__X__) (IS_IPAD ? (__X__) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPAD) : (__X__ * WIDTH_IPHONE_4 / WIDTH_IPAD)))
#define cy_pad(__Y__) (IS_IPAD ? (__Y__) : (__Y__ * HEIGHT_IPHONE / HEIGHT_IPAD))
Run Code Online (Sandbox Code Playgroud)


D-e*_*per 5

if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
    // This is iPhone 5 screen
} else {
    // This is iPhone 4 screen
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

153061 次

最近记录:

6 年,4 月 前