web-dev-qa-db-ja.com

ポイント値でのiPhone 6/6 +画面サイズの検出

新しく発表されたiPhone 6を考えると 画面サイズ

iPhone 6: 1334h * 750w @2x (in points: 667h * 375w)
iPhone 6+: 1920 * 1080 @3x (in points: 640h * 360w)

ユーザーのデバイスがどの画面サイズであるかを検出できるコードがあり、ユーザーのデバイスに合わせてUIImagesおよびその他の素材を調整およびサイズ調整できるかどうか疑問に思っていました。

これまでのところ、私は以下を使用しています。

- (NSString *) platform{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    return platform;
}

- (NSString *) platformString{
    NSString *platform = [self platform];
    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"Verizon iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone5,3"])    return @"iPhone 5c (GSM)";
    if ([platform isEqualToString:@"iPhone5,4"])    return @"iPhone 5c (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone6,1"])    return @"iPhone 5s (GSM)";
    if ([platform isEqualToString:@"iPhone6,2"])    return @"iPhone 5s (GSM+CDMA)";
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"])      return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([platform isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([platform isEqualToString:@"iPad2,7"])      return @"iPad Mini (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([platform isEqualToString:@"iPad3,2"])      return @"iPad 3 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,3"])      return @"iPad 3 (GSM)";
    if ([platform isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([platform isEqualToString:@"iPad3,5"])      return @"iPad 4 (GSM)";
    if ([platform isEqualToString:@"iPad3,6"])      return @"iPad 4 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad4,1"])      return @"iPad Air (WiFi)";
    if ([platform isEqualToString:@"iPad4,2"])      return @"iPad Air (Cellular)";
    if ([platform isEqualToString:@"iPad4,4"])      return @"iPad mini 2G (WiFi)";
    if ([platform isEqualToString:@"iPad4,5"])      return @"iPad mini 2G (Cellular)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";
    if ([platform isEqualToString:@"x86_64"])       return @"Simulator";
    return platform;
}

そのため、iPhone7,1iPhone7,2はiPhone 6であり、iPhone7,3iPhone7.4はプラスであると想定する必要がありますか?誰かがそれを素晴らしく伝えるためのより具体的な方法を持っているなら、ありがとう。

59
daspianist

最初の画面はデバイス画面になります。新しい携帯電話の起動画像を前に追加する必要があることに注意してください。そうしないと、アプリは古いアプリのズームモードで実行されます。 注:これは、iOS 8以降のバージョンでのみ機能します

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
          NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

IPhone 6 Plusを検出するためのコード:

#define IS_PAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_PHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)

-(BOOL)iPhone6PlusDevice{
    if (!IS_PHONE) return NO;
    if ([UIScreen mainScreen].scale > 2.9) return YES;   // Scale is only 3 when not in scaled mode for iPhone 6 Plus
    return NO;
}

または

-(BOOL) iPhone6PlusUnZoomed{
    if ([self iPhone6PlusDevice]){
        if ([UIScreen mainScreen].bounds.size.height > 720.0) return YES;  // Height is 736, but 667 when zoomed.
    }
    return NO;
}

注:iPhone 6 Plusをチェックしている場合、ユーザーインターフェイスを調整するために.nativeScaleに依存しないでください。シミュレータと実際のデバイスでは異なる結果が得られるためです。以下のコメントのため。スケールはCGFloatであるため、一部のfloat値は決して等しくない可能性があるため、コードは等しいことを確認しないでください。


Launch Screenを追加した後、新しいiPhoneサイズを使用できます。そうしないと、アプリは引き続きスケーリングされて表示されます。

新しいiPhone X ????、X ????用に更新とX ????マックス

iPhone X ???? Max with @ 3xスケーリングのサイズ(Apple名:Super Retina HD 6.5ディスプレイ ")、座標空間:- 414 x 896ポイントおよび1242 x 2688ピクセル、458 ppi、デバイスの物理サイズは3.05 x 6.20インチまたは77.4 x 157.5mmです。

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X???? Max Screen bounds: (0.0, 0.0, 414.0, 896.0), Screen resolution: (0.0, 0.0, 1242.0, 2688.0), scale: 3.0

iPhone X ???? with @ 2xスケーリングのサイズ(Apple名:Super Retina HD 6.1 "ディスプレイ)、座標空間:- 414 x 896ポイントおよび828 x 1792ピクセル、326 ppi、デバイスの物理サイズは2.98 x 5.94インチまたは75.7 x 150.9 mmです。

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X???? Screen bounds: (0.0, 0.0, 414.0, 896.0), Screen resolution: (0.0, 0.0, 828.0, 1792.0), scale: 2.0

iPhone X ????およびiPhone X with @ 3xスケーリングのサイズ(Apple名:Super Retina HD 5.8 "ディスプレイ)、座標空間:75 x 812ポイントおよび1125 x 2436ピクセル、458 ppi、デバイスの物理サイズは2.79 x 5.65インチまたは70.9 x 143.6 mmです。

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X???? and X Screen bounds: (0.0, 0.0, 375.0, 812.0), Screen resolution: (0.0, 0.0, 1125.0, 2436.0), scale: 3.0

iPhone 8、7、6 PlusおよびiPhone 8、7、6S Plus @ 3xスケーリングのサイズ(Apple名:Retina HD 5.5) 、座標空間:414 x 736ポイントおよび1242 x 2208ピクセル、401 ppi、画面の物理サイズは2.7 x 4.8インチまたは68 x 122 mm =:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

iPhone 6およびiPhone 6Sのサイズ@ 2xスケーリング(Apple名:Retina HD 4.7)、座標空間:75 x 667ポイントおよび750 x 1334ピクセル、326 ppi、画面の物理サイズは2.3 x 4.1インチまたは58 x 104 mm

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

iPhone 5は比較用に640 x 1136、iPhone 4 640 x 960です。

注:LaunchImagesをアップロードしないと、アプリはスケーリングされて実行され、正しいスケーリングや画面サイズが表示されません。

Comparing iPhone 6 and 6 Plus

101

あなたがここでマクロを好むなら、それはあなたがiPhoneモデルを区別するのに使用できるものです。これらはポイント値に基づいています。

#define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)480) < DBL_EPSILON)
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)
32
bkhayll

次のコードを使用して、どのデバイスが実行されているかを判断します(少し高速で汚れていますが、うまくいきます)

if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){

    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    if( screenHeight < screenWidth ){
        screenHeight = screenWidth;
    }

    if( screenHeight > 480 && screenHeight < 667 ){
        NSLog(@"iPhone 5/5s");
    } else if ( screenHeight > 480 && screenHeight < 736 ){
        NSLog(@"iPhone 6");
    } else if ( screenHeight > 480 ){
        NSLog(@"iPhone 6 Plus");
    } else {
        NSLog(@"iPhone 4/4s");
    }
}

(これは、適切なスプラッシュ画面を追加してiPhone 6/6 Plusが有効になっている場合にのみ機能します)

18
Roland Keesom

wiki の更新されたリストを確認してください。iPhone6では7,2、iPhone 6 plusでは7,1が得られました。

5
user3344236

物理デバイスでは、iPhone 6 Plusのメイン画面の境界は2208x1242で、nativeBoundsは1920x1080です。物理ディスプレイのサイズを変更するには、ハードウェアのスケーリングが必要です。

シミュレーターでは、iPhone 6 Plusのメイン画面の境界とnativeBoundsは両方とも2208x1242です。

つまり、ビデオ、OpenGL、およびピクセルを扱うCALayersに基づくその他のものは、デバイス上の実際の1920x1080フレームバッファー(またはsim上の2208x1242)を処理します。 UIKitでポイントを処理することは、2208x1242(x3)の境界を処理し、デバイスで適切にスケーリングされます。

シミュレーターは、デバイスでスケーリングを行っているのと同じハードウェアにアクセスできません。また、ハードウェアとは異なる結果を生成するため、ソフトウェアでシミュレートすることには大きな利点はありません。したがって、シミュレートされたデバイスのメイン画面のnativeBoundsを物理デバイスのメイン画面の境界に設定することは理にかなっています。

iOS 8は、開発者がUIScreenに対応するCADisplayの解像度を決定できるように、UIScreen(nativeScaleおよびnativeBounds)にAPIを追加しました。

次のマクロを使用して、ネイティブスケールに基づいてiPhone 6 Plusを検出できます。

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
4
sweepy_

Hannes Sverrissonの答えはほぼ正しいです。 iPhone 6の座標系は、実際には5秒よりも大きく、彼のコードを使用しています。

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
      NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

正しい起動画像を提供するアプリの座標系は次のとおりです。

@ 2xスケーリングのiPhone 6(Retina HD 4.7)のサイズ、座標空間:375 x 667および750 x 1334の実際のポイント:

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

@ 3xスケーリングのiPhone 6 Plus(Retina HD 5.5)のサイズ、座標空間:414 x 736および1242 x 2208の実際のポイント:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000
4
Paul Buchanan

IOS 7でビルドされたアプリでiPhone 6 Plusを検出する必要がありました。nativeScaleは[UIScreen mainScreen]で使用できないため、[UIScreen mainScreen] scaleを使用しようとしましたが、2.0が返されました。そこで、iOS 7でiPhone 6 Plusを検出するためにこのソリューションを思いつきました(iOS 8でも動作するはずです):

-(BOOL)iPhone6Plus{
BOOL isiPhone6Plus = NO;
SEL selector = NSSelectorFromString(@"scale");
if ([[UIScreen mainScreen] respondsToSelector:selector]) {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:[UIScreen mainScreen]];
    [invocation invoke];
    float returnValue;
    [invocation getReturnValue:&returnValue];
    if (returnValue == 3.0) {
        isiPhone6Plus = YES;
    }
    NSLog(@"ScaleFactor %1.2f", returnValue);
}
return isiPhone6Plus;

}

このコードの興味深い部分は、NSInvocationを使用すると、スケールセレクターの戻り値が3.0になることです。 iOS 7でこのメソッドを直接呼び出すと、2.0が返されます。

3
Sven

これは、iOS 8のアプリで使用するものです。

window=[[[UIApplication sharedApplication] windows] firstObject];

NSLog(@"screenHeight=%f width=%f",window.frame.size.height,window.frame.size.width);

if (window.frame.size.height == 480) {

        do stuff here... 
    }

Xcode6/iOS 8より前は、これを使用していましたが、サイズ変更可能なシミュレーターでは画面の境界が正しく機能しないか、少なくともXcode6ベータ版では機能しませんでした...

CGRect screenBounds=[[UIScreen mainScreen] bounds];

if (screenBounds.size.height >= 568) {

do stuff here...

}
3
David L

私にとってこれは私のために働く

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
    UIStoryboard *storyBoard;

    CGSize result = [[UIScreen mainScreen] bounds].size;
    CGFloat scale = [UIScreen mainScreen].scale;
    result = CGSizeMake(result.width * scale, result.height * scale);

    if(result.height == 1136){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_5" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 1334){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 2208){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6_plus" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 960){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_4" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    }

} else {

    UIStoryboard *storyBoard;

    storyBoard = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil];
    UIViewController *initViewController = [storyBoard instantiateInitialViewController];
    [self.window setRootViewController:initViewController];

}
2
oscar castellon

3つのデバイスはすべて(ほぼ)インチあたりのポイント数が同じです。したがって、画像は自動的に同じ物理サイズになります。

[[UIScreen mainScreen] bounds]を使用して、画面上の合計ポイント数を取得します。本当に必要な場合は、163で割っておおよそのサイズをインチで取得します。

6+は1080pバッファーにレンダリングしないため、1080pを返さないことに注意してください。 @ 3xアセットを使用して、出力が1インチあたり約160ポイントになるようにレンダリングします。

推測する必要はありません。

例えば。このコードを書く場合:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 163, 163)];
view.backgroundColor = [UIColor redColor];
[self.view addSubview:view];

すべてのiOSデバイスで、物理的にほぼ同じサイズ(1インチ四方)のビューが表示されます。

Appleはすでに大変な仕事をしているので、そうする必要はありません。

2
Tommy

IPhone 6 Plusで画面サイズを読み取るときに覚えておくべき興味深いことは、「ズーム」モードに設定すると、iPhone 6の高さ(667)として表示され、「標準」に設定すると表示されることです。 (736)として表示されます。本当に重要ではありませんが、何らかの理由でデバイスの種類を明確に知りたい場合(Maybe Reporting)、これはあなたをだますことができます。

this を参照してください。

1
Shippy

this を使用している更新済みのソースコードを次に示します。

iPhone 6およびiPhone 6 Plusモデルが追加されました。

1
Sergey Filippov

これはxcode 5でのコンパイルが保証されています(この時点でxocde 6はまだ不安定です。現在、xcode 6であるベータ版ソフトウェアを使用して、App Storeの承認のためにiTunes Connectにipaを送信することはできません)

問題は、xcode 5がnativeScaleセレクターを認識しないことです。これは、実行時にこれを行う方法です。

+ (BOOL)isIphone6Plus
{
    SEL selector = NSSelectorFromString(@"nativeScale");
    if ([[UIScreen mainScreen] respondsToSelector:selector]) {
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                        [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIScreen mainScreen]];
            [invocation invoke];
            float returnValue;
            [invocation getReturnValue:&returnValue];
            NSLog(@"::: this is native scale %f", returnValue);
            return (returnValue == 3.0f);
    } else {
        // iphone 6 plus come prepackaged with iOS8.. 
        // so if the phone doesn't know what nativeScale means
        // it's not an iphone6plus phone
        return NO;
    }
}
1
abbood

上記の答えが除外している主要なことの1つは、iOS7以下では、画面境界の[[UIScreen mainScreen] bounds]をチェックすると、携帯電話の向きに関係なく常に同じ幅と高さをリストするという事実ですしたがって、横向きモードのiPhone5の場合、幅は320、高さは568と表示されますが、iOS8ではこれが変更され、同じiPhone5が横向きの場合、幅は568、高さは320と表示されます。以下は、これを説明するメソッドです。

+ (BOOL) deviceHasFourInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:568.0];
}

+ (BOOL) deviceHasFourPointSevenInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:667.0];
}

+ (BOOL) deviceHasFivePointFiveInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:3.0 height:736.0];
}

+ (BOOL) deviceHasScreenWithIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom scale:(CGFloat)scale height:(CGFloat)height
{
    CGRect mainScreenBounds = [[UIScreen mainScreen] bounds];
    CGFloat mainScreenHeight;

    if ([OperatingSystemVersion operatingSystemVersionLessThan:@"8.0"])
    {
        mainScreenHeight = mainScreenBounds.size.height;
    }
    else
    {
        mainScreenHeight = (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ? mainScreenBounds.size.width : mainScreenBounds.size.height;
    }

    if ([[UIDevice currentDevice] userInterfaceIdiom] == userInterfaceIdiom && [[UIScreen mainScreen] scale] == scale && mainScreenHeight == height)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

また、付随するOperatingSystemクラスメソッドもここにあります。

+ (NSString *) currentOperatingSystemVersion
{
    return [[UIDevice currentDevice] systemVersion];
}
+ (BOOL) operatingSystemVersionLessThanOrEqualTo:(NSString *) operatingSystemVersionToCompare
{
    return ([[self currentOperatingSystemVersion] compare: operatingSystemVersionToCompare options:NSNumericSearch] != NSOrderedDescending);    
}
0
Ser Pounce

スイフト4

if(kSize.width == 320){
             //iphone se
}else if(kSize.width == 375 && kSize.height == 667){
             //iphone 7 / 8
}else if(kSize.width == 375){
            //iphone x
}else if(kSize.width == 414){
           //iphone 7 plus/ 8 plus
}

kSizeは画面CGSize

let kSize = UIScreen.main.bounds.size

0
Kishore Kumar