42
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iPhone Xをネイティブ解像度から判定する

Last updated at Posted at 2017-09-14

iPhone Xだけを判定したい場合があると思います。
ベストプラクティスではないかもしれませんが何かありましたら教えてください。

  • iOS 11以降であることを前提としています。
  • nativeBounds(iOS 8.0, *)を見ているのでiPhone XがDisplay Zoomモード(存在するかは未確認)であっても対応可能です。
  • ポートレイトモード、ランドスケープモードの両方に対応しています。

Swift

グローバル変数

let is_iPhoneX: Bool = {
    guard #available(iOS 11.0, *),
        UIDevice().userInterfaceIdiom == .phone else {
            return false
    }
    let nativeSize = UIScreen.main.nativeBounds.size
    let (w, h) = (nativeSize.width, nativeSize.height)
    let (d1, d2): (CGFloat, CGFloat) = (1125.0, 2436.0)
    return (w == d1 && h == d2) || (w == d2 && h == d1)
}()

Objective-C

UIDeviceカテゴリ

UIDevice+Extension.h
@import UIKit;

@interface UIDevice (Extension)
+ (BOOL)is_iPhoneX;
@end

GCDを用いて初回1度だけ判定してstatic変数に格納しています。

UIDevice+Extension.m
#import "UIDevice+Extension.h"

@implementation UIDevice (Extension)

+ (BOOL)is_iPhoneX
{
    static BOOL result = NO;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (@available(iOS 11.0, *)) {
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
                CGSize nativeSize = UIScreen.mainScreen.nativeBounds.size;
                CGFloat w =  nativeSize.width;
                CGFloat h =  nativeSize.height;
                CGFloat d1 = 1125;
                CGFloat d2 = 2436;
                result = (w == d1 && h == d2) || (w == d2 && h == d1);
            }
        }
    });
    
    return result;
}

@end

命名規則に反してis_iPhoneXとしていますが、iPhoneが含まれる変数や関数をキャメルケースでつなげるとき悩みますね。

使う時

ViewController.m
#import "UIDevice+Extension.h"
...

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    if (UIDevice.is_iPhoneX) {
        NSLog(@"is iPhoneX");
    }
    else {
        NSLog(@"is not iPhoneX");
    }
}

マクロ & インライン関数

nativeBoundsが使えるiOS 8以降を前提にしています。

NS_INLINE BOOL checkScreenSize (CGFloat d1, CGFloat d2) {
    CGSize nativeSize = UIScreen.mainScreen.nativeBounds.size;
    CGFloat w =  nativeSize.width;
    CGFloat h =  nativeSize.height;
    return (w == d1 && h == d2) || (w == d2 && h == d1);
}
#define IS_IPHONE          (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_OS_11_OR_LATER  (UIDevice.currentDevice.systemVersion.floatValue >= 11.0)
#define IS_IPHONE_X        (IS_IPHONE && IS_OS_11_OR_LATER && checkScreenSize(1125, 2436))

参考: :link: How can I detect whether a user has an iPhone 6 Plus in standard or zoomed mode?

Display Zoomモードの判定

iPhone 6から導入された機能で、小さい文字などが見えにくい人のために設定アプリの「画面表示と明るさ」「拡大表示」から解像度を一回り下げることができます。実機で確認できるようなのでiPhone Xも対応しているかは不明です。

このときUIScreen.mainScreen.boundsの値が変更されてしまいますがUIScreen.mainScreen.nativeBoundsは不変です。

UIScreen.mainScreen.scaleUIScreen.mainScreen.nativeScaleの値が違っていたらDisplay Zoomモードであると判断できます。scaleではなくnativeScaleの方が変化します。

swift
if (UIScreen.main.scale != UIScreen.main.nativeScale) {
    // display zoom mode
}
objc
if (UIScreen.mainScreen.scale != UIScreen.mainScreen.nativeScale) {
    // display zoom mode
}
42
27
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?