264

可能重复:
如何为 iPhone 5 屏幕分辨率开发或迁移应用程序?

我只是想知道我们应该如何处理 iPhone 5 更大的屏幕尺寸。

由于它在高度上有更多像素,因此使用坐标的 GCRectMake 之类的东西(并且由于视网膜/非视网膜问题只是将像素加倍)将无法在版本之间无缝工作,就像我们得到Retina时发生的那样。

我们是否必须像 iPad 一样设计两个故事板?

我个人认为Apple不会要求您每次必须绘制某些东西时都检查屏幕尺寸,就像许多答案所说的那样。iPad会发生这种情况吗?

4

8 回答 8

209

从我今天的演示中可以看出,所有应用程序都将继续在垂直拉伸的屏幕上运行。它们将被装上信箱,或者基本上额外的 88 点高度将只是黑色。

如果你只打算支持 iOS 6+,那么一定要考虑使用 Auto Layout。它删除了所有固定的布局处理,而是使用约束来布局。没有什么是硬编码的,你的生活会变得简单得多。

但是,如果您必须支持较旧的 iOS,那么它真的取决于您的应用程序。大多数使用标准导航栏和/或标签栏的应用程序可以简单地扩展中间的内容以用完这些额外的点。将中心内容的自动调整大小蒙版设置为双向扩展。

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

它对表格视图开箱即用效果很好,但是,如果您的应用程序使用像素完美的布局来显示内容,那么您最好的选择是重新想象内容,以便它可以适应不同的高度。

如果这不可能,那么剩下的唯一选择就是拥有两个 UI(iPhone 5 之前和 iPhone 5)。

如果这听起来很难看,那么您可以使用默认的信箱模型,其中额外的点/像素只显示为黑色。

编辑

要使您的应用程序能够在 iPhone 5 上运行,您需要添加启动器图像的视网膜版本。它应该被命名为Default-568h@2x.png. 它必须是视网膜质量 - 这里没有向后兼容性:)

你也可以从 Xcode 中选择这个图像。转到目标,然后在 Summary 部分下,查找 Launch Images。图像的大小必须为 640x1136 像素。如果有帮助,这是在哪里找到它的屏幕截图。

Xcode 截图

于 2012-09-12T22:02:30.223 回答
84

您需要添加一个 640x1136 像素的PNG图像Default-568h@2x.png

我创建了一个小的 UIDevice 类别来处理所有的屏幕分辨率。你可以在这里得到它,但代码如下:

文件UIDevice+Resolutions.h

enum {
    UIDeviceResolution_Unknown           = 0,
    UIDeviceResolution_iPhoneStandard    = 1,    // iPhone 1,3,3GS Standard Display  (320x480px)
    UIDeviceResolution_iPhoneRetina4    = 2,    // iPhone 4,4S Retina Display 3.5"  (640x960px)
    UIDeviceResolution_iPhoneRetina5     = 3,    // iPhone 5 Retina Display 4"       (640x1136px)
    UIDeviceResolution_iPadStandard      = 4,    // iPad 1,2,mini Standard Display   (1024x768px)
    UIDeviceResolution_iPadRetina        = 5     // iPad 3 Retina Display            (2048x1536px)
}; typedef NSUInteger UIDeviceResolution;

@interface UIDevice (Resolutions)

- (UIDeviceResolution)resolution;

NSString *NSStringFromResolution(UIDeviceResolution resolution);

@end

文件UIDevice+Resolutions.m

#import "UIDevice+Resolutions.h"

@implementation UIDevice (Resolutions)

- (UIDeviceResolution)resolution
{
    UIDeviceResolution resolution = UIDeviceResolution_Unknown;
    UIScreen *mainScreen = [UIScreen mainScreen];
    CGFloat scale = ([mainScreen respondsToSelector:@selector(scale)] ? mainScreen.scale : 1.0f);
    CGFloat pixelHeight = (CGRectGetHeight(mainScreen.bounds) * scale);

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
        if (scale == 2.0f) {
            if (pixelHeight == 960.0f)
                resolution = UIDeviceResolution_iPhoneRetina4;
            else if (pixelHeight == 1136.0f)
                resolution = UIDeviceResolution_iPhoneRetina5;

        } else if (scale == 1.0f && pixelHeight == 480.0f)
            resolution = UIDeviceResolution_iPhoneStandard;

    } else {
        if (scale == 2.0f && pixelHeight == 2048.0f) {
            resolution = UIDeviceResolution_iPadRetina;

        } else if (scale == 1.0f && pixelHeight == 1024.0f) {
            resolution = UIDeviceResolution_iPadStandard;
        }
    }

    return resolution;
 }

 @end

这就是您需要使用此代码的方式。

1) 将上面的 UIDevice+Resolutions.h & UIDevice+Resolutions.m 文件添加到你的项目中

2) 将 #import "UIDevice+Resolutions.h" 行添加到您的 ViewController.m

3)添加此代码以检查您正在处理的设备版本

int valueDevice = [[UIDevice currentDevice] resolution];

    NSLog(@"valueDevice: %d ...", valueDevice);

    if (valueDevice == 0)
    {
        //unknow device - you got me!
    }
    else if (valueDevice == 1)
    {
        //standard iphone 3GS and lower
    }
    else if (valueDevice == 2)
    {
        //iphone 4 & 4S
    }
    else if (valueDevice == 3)
    {
        //iphone 5
    }
    else if (valueDevice == 4)
    {
        //ipad 2
    }
    else if (valueDevice == 5)
    {
        //ipad 3 - retina display
    }
于 2012-09-13T14:48:18.340 回答
56

我刚刚完成更新并将我的一个应用程序的 iOS 6.0 版本发送到商店。此版本向后兼容 iOS 5.0,因此我保留了该shouldAutorotateToInterfaceOrientation:方法并添加了如下所列的新方法。

我必须执行以下操作:

iOS 6 中的自动旋转正在发生变化。在 iOS 6 中,shouldAutorotateToInterfaceOrientation:不推荐使用 UIViewController 的方法。取而代之的是,您应该使用supportedInterfaceOrientationsForWindow:andshouldAutorotate方法。因此,我添加了这些新方法(并保留旧方法以兼容 iOS 5):

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown;    
}
  • 使用视图控制器的viewWillLayoutSubviews方法并使用视图的边界矩形调整布局。
  • 模态视图控制器:不再在任何对其 自身进行全屏呈现的视图控制器上调用willRotateToInterfaceOrientation:duration:
    willAnimateRotationToInterfaceOrientation:duration:和方法——例如,.
    didRotateFromInterfaceOrientation:
    presentViewController:animated:completion:
  • 然后我修复了需要它的视图的自动布局。
  • 将模拟器中用于启动视图和 iTunes 商店视图的图像复制到 PhotoShop 中,并将它们导出为 png 文件。
  • 默认图片名称为:Default-568h@2x.png,尺寸为640×1136。它还允许为相同的纵向模式提供 640×1096(删除状态栏)。如果您的应用程序仅允许 iPhone 上的横向显示,也可以在横向模式下提供类似的尺寸。
  • 我已经放弃了对 iOS 4 的向后兼容性。主要原因是因为对armv6代码的支持已被放弃。因此,我现在能够支持的所有设备(正在运行armv7)都可以升级到 iOS 5。
  • 我还生成了支持 iPhone 5 的 armv7s 代码,因此在更新之前不能使用任何第三方框架(如 Admob 等)。

由于旋转的变化,这只是记住在 iOS 5 和 iOS 6 中测试自动旋转。

于 2012-09-13T00:13:03.940 回答
26

不。

if ([[UIScreen mainScreen] bounds].size.height > 960)

在 iPhone 5 上是错误的

if ([[UIScreen mainScreen] bounds].size.height == 568)
于 2012-09-14T13:30:34.070 回答
17
@interface UIDevice (Screen)
typedef enum
{
    iPhone          = 1 << 1,
    iPhoneRetina    = 1 << 2,
    iPhone5         = 1 << 3,
    iPad            = 1 << 4,
    iPadRetina      = 1 << 5

} DeviceType;

+ (DeviceType)deviceType;
@end

.m

#import "UIDevice+Screen.h"
@implementation UIDevice (Screen)

+ (DeviceType)deviceType
{
    DeviceType thisDevice = 0;
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
    {
        thisDevice |= iPhone;
        if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
        {
            thisDevice |= iPhoneRetina;
            if ([[UIScreen mainScreen] bounds].size.height == 568)
                thisDevice |= iPhone5;
        }
    }
    else
    {
        thisDevice |= iPad;
        if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
            thisDevice |= iPadRetina;
    }
    return thisDevice;
}

@end

这样,如果您想检测它是否只是 iPhone 或 iPad(无论屏幕尺寸如何),您只需使用:

if ([UIDevice deviceType] & iPhone) 

或者

if ([UIDevice deviceType] & iPad)

如果您只想检测 iPhone 5,您可以使用

if ([UIDevice deviceType] & iPhone5)

与 Malcoms 的回答相反,您需要检查它是否是 iPhone,

if ([UIDevice currentResolution] == UIDevice_iPhoneHiRes || 
    [UIDevice currentResolution] == UIDevice_iPhoneStandardRes || 
    [UIDevice currentResolution] == UIDevice_iPhoneTallerHiRes)`

这两种方式都没有比彼此更大的优势,这只是个人喜好。

于 2012-09-13T17:06:09.063 回答
5

@Pascal 对 OP 问题的评论是正确的。通过简单地添加图像,它会删除黑色边框,并且应用程序将使用整个高度。

您将需要通过确定设备正在使用更大的显示器来调整任何 CGRects。即,如果您需要与屏幕底部对齐的东西。

我确信有一个内置方法,但我没有看到任何东西,而且很多东西仍在 NDA 之下,所以我们在应用程序中使用的方法很简单,是一个全局函数。将以下内容添加到您的 .pch 文件中,然后通过简单的if( is4InchRetina() ) { ... }调用来调整您的 CGRects 等。

static BOOL is4InchRetina()
{
    if (![UIApplication sharedApplication].statusBarHidden && (int)[[UIScreen mainScreen] applicationFrame].size.height == 548 || [UIApplication sharedApplication].statusBarHidden && (int)[[UIScreen mainScreen] applicationFrame].size.height == 568)
        return YES;

    return NO;
}
于 2012-09-14T14:27:25.287 回答
3

我认为您可以[UIScreen mainScreen].bounds.size.height为您的对象使用和计算步长。当您计算步长时,您可以为两种分辨率设置坐标。

或者你可以得到像上面的高度和if(iphone5) then... else if(iphone4) then... else if(ipad)。像这样的东西。

如果您使用情节提要,那么我认为您必须为新 iPhone 创建新的。

于 2012-09-12T21:44:45.967 回答
3

由于它在高度上有更多像素,因此使用坐标的 GCRectMake 之类的东西不会在版本之间无缝工作,就像我们获得 Retina 时发生的那样。

好吧,它们Retina 显示器的工作原理相同——只是 CoreGraphics 坐标系中的 1 个单位对应于 2 个物理像素,但您不需要/不必做任何事情,逻辑保持不变。(您是否真的尝试过在视网膜 iPhone 上运行您的非视网膜应用程序之一?

对于实际的问题:这就是为什么你不应该使用明确的 CGRectMakes 和 co ......这就是为什么你有像[[UIScreen mainScreen] applicationFrame].

于 2012-09-12T21:45:53.470 回答