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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12446990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:10:10  来源:igfitidea点击:

How to detect iPhone 5 (widescreen devices)?

iphoneiosobjective-cscreendevice

提问by Finn Gaida

I've just upgraded to XCode 4.5 GM and found out that you can now apply the '4" Retina' size to your view controller in the storyboard.

我刚刚升级到 XCode 4.5 GM,发现您现在可以将“4” Retina 尺寸应用于故事板中的视图控制器。

Now if I want to create an application that runs on both iPhone 4 and 5, of course I have to build every window twice, but I also have to detect whether the user has an iPhone with 3.5" or 4" screen and then apply the view.

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

How should I do that?

我该怎么做?

回答by Macmade

First of all, you shouldn't rebuild all your views to fit a new screen, nor use different views for different screen sizes.

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

Use the auto-resizingcapabilities of iOS, so your views can adjust, and adapt any screen size.

使用iOS的自动调整大小功能,因此您的视图可以调整和适应任何屏幕尺寸。

That's not very hard, read some documentationabout that. It will save you a lot of time.

这不是很难,阅读一些关于它的文档。它会为您节省很多时间。

iOS 6 also offers new features about this.
Be sure to read the iOS 6 API changelogon Apple Developer website.
And check the new iOS 6 AutoLayoutcapabilities.

iOS 6 还提供了与此相关的新功能。
请务必阅读Apple Developer 网站上的iOS 6 API 更新日志
并检查新的 iOS 6 AutoLayout功能。

That said, if you really need to detect the iPhone 5, you can simply rely on the screen size.

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

[ [ UIScreen mainScreen ] bounds ].size.height

The iPhone 5's screen has a height of 568.
You can imagine a macro, to simplify all of this:

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

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

The use of fabswith the epsilon is here to prevent precision errors, when comparing floating points, as pointed in the comments by H2CO3.

fabs正如 H2CO3 的评论中所指出的,在比较浮点时,使用epsilon 是为了防止精度错误。

So from now on you can use it in standard if/else statements:

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

if( IS_IPHONE_5 )
{}
else
{}

Edit - Better detection

编辑 - 更好的检测

As stated by some people, this does only detect a widescreen, not an actual iPhone 5.

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

Next versions of the iPod touch will maybe also have such a screen, so we may use another set of macros.

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

Let's rename the original macro IS_WIDESCREEN:

让我们重命名原始宏IS_WIDESCREEN

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

And let's add model detection macros:

让我们添加模型检测宏:

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

This way, we can ensure we have an iPhone model ANDa widescreen, and we can redefine the IS_IPHONE_5macro:

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

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

Also note that, as stated by @LearnCocos2D, this macros won't work if the application is not optimised for the iPhone 5 screen (missing the [email protected] image), as the screen size will still be 320x480 in such a case.

另请注意,如@LearnCocos2D 所述,如果应用程序未针对 iPhone 5 屏幕进行优化(缺少 [email protected] 图像),则此宏将不起作用,因为在这种情况下屏幕尺寸仍为 320x480一个案例。

I don't think this may be an issue, as I don't see why we would want to detect an iPhone 5 in a non-optimized app.

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

IMPORTANT - iOS 8 support

重要 - iOS 8 支持

On iOS 8, the boundsproperty of the UIScreenclass now reflects the device orientation.
So obviously, the previous code won't work out of the box.

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

In order to fix this, you can simply use the new nativeBoundsproperty, instead of bounds, as it won't change with the orientation, and as it's based on a portrait-up mode.
Note that dimensions of nativeBoundsis measured in pixels, so for an iPhone 5 the height will be 1136instead of 568.

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

If you're also targeting iOS 7 or lower, be sure to use feature detection, as calling nativeBoundsprior to iOS 8 will crash your app:

如果您还针对 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 */
}

You can adapt the previous macros the following way:

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

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

And obviously, if you need to detect an iPhone 6 or 6 Plus, use the corresponding screen sizes.

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

回答by hfossli

Tested and designed for any combination of SDK and OS:

针对 SDK 和操作系统的任意组合进行测试和设计:

Swift

迅速

Added iPad types. iPad 2 and iPad mini are non-retina iPads. While iPad Mini 2 & above, iPad 3, 4, iPad Air, Air 2, Air 3, and iPad Pro 9.7 have same logical resolution of 1024. iPad Pro has maxLength of 1366.Reference

添加了 iPad 类型。iPad 2 和 iPad mini 是非视网膜 iPad。iPad Mini 2 及以上、iPad 3、4、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
    }
}

See it in action https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

看到它在行动 https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.

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

Objective-C

目标-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)

Usage: http://pastie.org/9687735

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

Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.

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

回答by Samrat Mazumdar

Really simple solution

非常简单的解决方案

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

回答by Sam B

We now need to account for iPhone 6 and 6Plus screen sizes. Here's an updated answer

我们现在需要考虑 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
}

Some useful info

一些有用的信息

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"

回答by LearnCocos2D

I've taken the liberty to put the macro by Macmade into a C function, and name it properly because it detects widescreen availabilityand NOTnecessarily the iPhone 5.

我冒昧通过Macmade把宏成C函数,因为它检测到正确命名为宽屏可用性必然是iPhone 5。

The macro also doesn't detect running on an iPhone 5 in case where the project doesn't include the [email protected]. Without the new Default image, the iPhone 5 will report a regular 480x320 screen size (in points). So the check isn't just for widescreen availability but for widescreen mode being enabledas well.

如果项目不包含[email protected],宏也不会检测到在 iPhone 5 上运行。如果没有新的默认图像,iPhone 5 将报告常规的 480x320 屏幕尺寸(以磅为单位)。因此,该检查不仅针对宽屏可用性,还针对是否启用宽屏模式

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

回答by Ginger

Here is our codes, test passed on ios7/ios8 for iphone4,iphone5,ipad,iphone6,iphone6p, no matter on devices or simulator:

这是我们的代码,在 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 )

回答by Borbea

I used hfossli's answer and translated it to Swift

我使用了 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)

回答by OMGPOP

this is the macro for my cocos2d project. should be the same for other apps.

这是我的 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))

回答by D-eptdeveloper

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

回答by zubko

In Swift, iOS 8+ project I like to make an extension on UIScreen, like:

在 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;
    }

}

(NOTE: nativeBoundsis in pixels).

(注意:nativeBounds以像素为单位)。

And then the code will be like:

然后代码将如下所示:

if UIScreen.mainScreen().isPhone4 {
    // do smth on the smallest screen
}

So the code makes it clear that this is a check for the main screen, not for the device model.

所以代码清楚地表明这是对主屏幕的检查,而不是对设备型号的检查。