デバイスがiPhone Xかどうかを検出する


262

私のiOSアプリはカスタムの高さを使用しているためUINavigationBar、新しいiPhone Xで問題が発生します。

アプリがiPhone Xで実行されているかどうかをプログラムで(Objective-Cで)確実に検出する方法を誰かがすでに知っていますか?

編集:

もちろん、画面のサイズをチェックすることは可能ですが、TARGET_OS_IPHONEiOSを検出するような「組み込み」の方法があるのでしょうか...

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    if (screenSize.height == 812)
        NSLog(@"iPhone X");
}

編集2:

私の質問はリンクされた質問の複製であるとは思いません。もちろん、現在のデバイスのさまざまな特性を「測定」し、その結果を使用してどのデバイスを使用するかを決定する方法があります。しかし、私が最初の編集で強調しようとしたので、これは私の質問の実際のポイントではありませんでした。

実際の質問は次のとおりです。「現在のデバイスがiPhone X(たとえば、SDK機能によって)であるかどうかを直接検出することはできますか、それとも間接測定を使用する必要がありますか?

これまでの回答では、「いいえ、直接的な方法はありません。測定が進むべき道」と答えています。


iPhone Xの画面解像度は他のものとは異なります。
El Tomato

2
はい、編集で述べたように、画面サイズを確認できます。しかし質問は、デバイスの種類を照会する「直接」方法ではなく、「間接的に」測定があれば、です...
アンドレイヘルフォルト

3
著者は画面の解像度ではなく、デバイスの種類を取得したいだけです。マシン名を直接確認してみませんか? @lubilisは正しいです。
イタチ

2
アップルが推奨するセーフエリアガイドを使用しないのはなぜですか?
holex

4
重要、将来の開発者:現在の上位のソリューションが示唆するように、これを利用して画面の高さを検出しないでください。将来のデバイスで誤検知が発生する可能性があるため、これは悪いことです。UIWindowがまだレンダリングされていない場合(AppDelegateの初期化関数など)は機能せず、ランドスケープアプリでは機能せず、スケールが設定されているとシミュレータで失敗する可能性があります。このようなことにはマジックナンバーを使用しないでください!ここで行ったように、ハードウェアフラグをチェックして成功を保証できます。stackoverflow.com
Albert Renshaw

回答:


383

あなたの質問に基づいて、答えはノーです。直接的な方法はありません。詳細については、ここで情報を取得できます。

そして

iPhone Xの高さは2436ピクセルです

デバイスの画面サイズと解像度

ここに画像の説明を入力してください

デバイスの画面サイズと向き

ここに画像の説明を入力してください

Swift 3以降

if UIDevice().userInterfaceIdiom == .phone {
    switch UIScreen.main.nativeBounds.height {
        case 1136:
            print("iPhone 5 or 5S or 5C")

        case 1334:
            print("iPhone 6/6S/7/8")

        case 1920, 2208:
            print("iPhone 6+/6S+/7+/8+")

        case 2436:
            print("iPhone X/XS/11 Pro")

        case 2688:
            print("iPhone XS Max/11 Pro Max")

        case 1792:
            print("iPhone XR/ 11 ")

        default:
            print("Unknown")
        }
    }

Objective-C

if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
    switch ((int)[[UIScreen mainScreen] nativeBounds].size.height) {
        case 1136:
            printf("iPhone 5 or 5S or 5C");
                break;

        case 1334:
            printf("iPhone 6/6S/7/8");
            break;

        case 1920, 2208:
            printf("iPhone 6+/6S+/7+/8+");
            break;

       case 2436:
            print("iPhone X/XS/11 Pro");
             break;

        case 2688:
            print("iPhone XS Max/11 Pro Max");
             break;

        case 1792:
            print("iPhone XR/ 11 ");
             break;

        default:
            printf("Unknown");
            break;
    }
}

Xamarin.iOS

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) {
    if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1136) {
        Console.WriteLine("iPhone 5 or 5S or 5C");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1334) {
        Console.WriteLine("iPhone 6/6S/7/8");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1920 || (UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2208) {
        Console.WriteLine("iPhone 6+/6S+/7+/8+");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2436) {
        Console.WriteLine("iPhone X, XS, 11 Pro");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2688) {
        Console.WriteLine("iPhone XS Max, 11 Pro Max");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1792) {
        Console.WriteLine("iPhone XR, 11");
    } else {
        Console.WriteLine("Unknown");
    }
}

次のようにあなたの質問に基づいて:

または、 intではなくscreenSize.heightfloatとして使用します。812.0f812

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
        // 812.0 on iPhone X, XS
        // 896.0 on iPhone XS Max, XR.

    if (screenSize.height >= 812.0f)
        NSLog(@"iPhone X");
    }

詳細については、iOSヒューマンインターフェイスガイドラインの次のページを参照してください。

スウィフト

で検出topNotch

ノッチを使用してiPhoneXを検出することを検討している人がいる場合は、「ランドスケープ」ではすべてのiPhoneで同じになることに注意してください。

var hasTopNotch: Bool {
    if #available(iOS 13.0,  *) {
        return UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.safeAreaInsets.top ?? 0 > 20
    }else{
     return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }

    return false
}

Objective-C

- (BOOL)hasTopNotch {
   if (@available(iOS 13.0, *)) {
       return [self keyWindow].safeAreaInsets.top > 20.0;
   }else{
       return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0;
   }
   return  NO;
}

- (UIWindow*)keyWindow {
    UIWindow        *foundWindow = nil;
    NSArray         *windows = [[UIApplication sharedApplication]windows];
    for (UIWindow   *window in windows) {
        if (window.isKeyWindow) {
            foundWindow = window;
            break;
        }
    }
    return foundWindow;
}

更新

userInterfaceIdiomuserInterfaceIdiomドキュメントで説明されているように、このプロパティを使用してデバイスタイプを識別しないでください。

ユニバーサルアプリケーションの場合、このプロパティを使用して、特定の種類のデバイスに合わせてアプリケーションの動作を調整できます。たとえば、iPhoneデバイスとiPadデバイスでは画面サイズが異なるため、現在のデバイスのタイプに基づいて異なるビューとコントロールを作成することができます。

つまり、このプロパティは、実行中のアプリのビュースタイルを識別するためだけに使用されます。ただし、iPhoneアプリ(ユニバーサルではない)はApp Store経由でiPadデバイスにインストールできます。その場合、もuserInterfaceIdiomを返しUIUserInterfaceIdiomPhoneます。

正しい方法は、を介してマシン名を取得することunameです。詳細については、以下を確認してください。


iPhone Xの解像度は、2436 x 1125ピクセルです。iphonesoft.fr
Medhi

1
@Medhi-iphone Xの解像度は-1125 x 2436ピクセル(
〜458

14
番号!iPhoneアプリ(ユニバースではない)は、App Storeを介してiPadデバイスにインストールできます。その場合、もuserInterfaceIdiomを返しUIUserInterfaceIdiomPhoneます。この答えは間違っています。
イタチ

1
@ ThreeCoins、Leo Dabusの提案に従って、plusデバイスの回答を更新してください。Plusシミュレータでは機能しますが、デバイスでは機能しません。
Hiren Gujarati

2
将来のデバイスで誤検知が発生する可能性があるため、これは悪いことです。UIWindowがまだレンダリングされていない場合(AppDelegate)は機能せず、ランドスケープアプリでは機能せず、スケールが設定されているとシミュレータで失敗する可能性があります。私がここで行ったように、ハードウェアフラグをチェックして成功を保証できます:stackoverflow.com/a/51511947/2057171
Albert Renshaw

101

もう1つの可能性。iOS11とiOS 12で機能します。これは、上部にノッチがあり、44のインセットがあるのはiPhone Xだけであるためです。

Objective-C:

    BOOL iPhoneX = NO;
    if (@available(iOS 11.0, *)) {
        UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
        if (mainWindow.safeAreaInsets.top > 24.0) {
            iPhoneX = YES;
        }
    }

スウィフト4:

/// Has safe area
///
/// with notch: 44.0 on iPhone X, XS, XS Max, XR.
///
/// without notch: 20.0 on iPhone 8 on iOS 12+.
///
static var hasSafeArea: Bool {
    guard #available(iOS 11.0, *), let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 24 else {
        return false
    }
    return true
}

そしてもちろん、横向きの場合は、左と右の安全領域インセットを確認する必要があるかもしれません。

編集:_windowはAppDelegateのUIWindowであり、このチェックはアプリケーションdidFinishLaunchingWithOptionsで行われます。

iOS 12で回答が更新され、トップ> 0ではなくトップ> 24かどうかを確認するようになりました。

編集:シミュレーターで、ハードウェアに移動し、通話中ステータスバーを切り替えます。これを行うと、ステータスバーの高さが、通話中のiOS 11またはiPhone XS iOS 12上のiPhone Xでは変更されないことがわかります。変化するのは時間のアイコンだけで、どちらの場合も緑の背景になります。ここにスナップがあります:

ここに画像の説明を入力してください


5
安全領域のインセットには、他のデバイスでステータスバーが表示されている場合は、その高さが含まれます。ステータスバーが表示されている場合、これが0であるかどうかのチェックのみのデバイスは、iPhoneのX.でない場合は、あなたを教えてくれます
IMcD23

3
「これはiPhone XやiPhone 11で壊れるかもしれません」とCookは言いました。
イタチ

11
私は少し適応して、if _window.safeAreaInsets != UIEdgeInsets.zeroどのデバイスの向きにも対応できるようにしました
Fraser

2
あなたが使用しない場合は.topsafeAreaInsets.bottomiPhone Xおよびその他のデバイス上の0で34になります
blwinters

7
警告:これを使用しないでください。iOS12で機能しなくなります。また、この場合のUIWindowの動作についても説明されていません。openradar.appspot.com/42372793
Steipete

73

実際のニーズに応じて、iPhone Xのさまざまな検出を実行する必要があります。

トップノッチ(ステータスバー、ナビゲーションバー)などを処理するため。

class var hasTopNotch: Bool {
    if #available(iOS 11.0, tvOS 11.0, *) {
        // with notch: 44.0 on iPhone X, XS, XS Max, XR.
        // without notch: 24.0 on iPad Pro 12.9" 3rd generation, 20.0 on iPhone 8 on iOS 12+.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 24
    }
    return false
}

下部のホームインジケーター(タブバー)などを処理するため。

class var hasBottomSafeAreaInsets: Bool {
    if #available(iOS 11.0, tvOS 11.0, *) {
        // with home indicator: 34.0 on iPhone X, XS, XS Max, XR.
        // with home indicator: 20.0 on iPad Pro 12.9" 3rd generation.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0 > 0
    }
    return false
}

背景サイズ、フルスクリーン機能など

class var isIphoneXOrBigger: Bool {
    // 812.0 on iPhone X, XS.
    // 896.0 on iPhone XS Max, XR.
    return UIScreen.main.bounds.height >= 812
}

注:最終的には UIDevice.current.userInterfaceIdiom == .phone
注。この方法では、LaunchScreenストーリーボードまたは適切なLaunchImagesが必要です。

背景の比率、スクロール機能など

class var isIphoneXOrLonger: Bool {
    // 812.0 / 375.0 on iPhone X, XS.
    // 896.0 / 414.0 on iPhone XS Max, XR.
    return UIScreen.main.bounds.height / UIScreen.main.bounds.width >= 896.0 / 414.0
}

注:このメソッドには、LaunchScreenストーリーボードまたは適切なLaunchImagesが必要です

分析、統計、追跡など

マシン識別子を取得し、文書化された値と比較します。

class var isIphoneX: Bool {
    var size = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    let model = String(cString: machine)
    return model == "iPhone10,3" || model == "iPhone10,6"
}

シミュレーターを有効なiPhone Xとして分析に含めるには:

class var isIphoneX: Bool {
    let model: String
    if TARGET_OS_SIMULATOR != 0 {
        model = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
    } else {
        var size = 0
        sysctlbyname("hw.machine", nil, &size, nil, 0)
        var machine = [CChar](repeating: 0, count: size)
        sysctlbyname("hw.machine", &machine, &size, nil, 0)
        model = String(cString: machine)
    }
    return model == "iPhone10,3" || model == "iPhone10,6"
}

iPhone XS、XS Max、XRを含めるには、「iPhone11」で始まるモデルを探します。

return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")

faceIDサポート用

import LocalAuthentication
/// will fail if user denies canEvaluatePolicy(_:error:)
class var canUseFaceID: Bool {
    if #available(iOS 11.0, *) {
        return LAContext().biometryType == .typeFaceID
    }
    return false
}

return LAContext().biometryType == .typeFaceIDユーザーがcanEvaluatePolicyを拒否した場合でもが機能することを期待していましたが、機能しません。それでも戻ります.none
Jeremy

まあ@ジェレミー、それは文書化された行動であり、アップルのプライバシーポリシーの結果です。メソッドの上にコメントがあるのはそのためです。
・クール

ああ、私はあなたのコメントを誤解しました。canEvaluatePolicyを使用すると失敗する可能性があるので、代わりに以下を使用してください。ユーザーがトグルに応答するまでデバイスにFace IDがあるかどうかを確認することを許可されており、それ以上確認することができないのは少し奇妙です。[設定]に移動してFace IDを切り替えるように促す有用なエラーメッセージを提供するにはどうすればよいですか?
ジェレミー

@ジェレミー私はiPhone Xを持っていないので、わかりません。上記のモデル検出(model == "iPhone10,3" || model == "iPhone10,6")を使用でき、canUseFaceIDfalseが返された場合は、ユーザーによって拒否されたことを意味します。
・クール

1
@MateoOlaya私の答えの中には、Appleによって拒否されるものはありません。すべてを使用できます。
クール2018

42

このようにして、寸法に応じてiPhone Xデバイスを検出できます。

迅速

if UIDevice().userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436 {
   //iPhone X
}

目的-C

if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone && UIScreen.mainScreen.nativeBounds.size.height == 2436)  {
  //iPhone X     
}

ここに画像の説明を入力してください

だが

これでは不十分です。もしAppleがiPhone Xと同じ寸法の次のiPhoneを発表したとしたらどうでしょう。そのため、ハードウェア文字列を使用してデバイスを検出するのが最善の方法です。

新しいデバイスの場合、ハードウェア文字列は次のとおりです。

iPhone 8- iPhone10,1またはiPhone 10,4

iPhone 8 Plus- iPhone10,2またはiPhone 10,5

iPhone X- iPhone10,3またはiPhone10,6


2
[UIDevice currentDevice]代わりに使用する必要があります[[UIDevice alloc] init]
S. Matsepura 2017年

ハードウェア文字列の唯一の問題は、それがシミュレータで機能しないことです
2018年

38

デバイスモデル/マシン名を確認しください。コード内のポイント/ピクセルカウントを直接使用しないでください。これはハードコードであり、デバイスハードウェアにとって意味がありません。デバイスモデルは、一致するデバイスのタイプの唯一の一意の識別子です

#import <sys/utsname.h>

NSString* deviceName()
{
    struct utsname systemInfo;
    uname(&systemInfo);

    return [NSString stringWithCString:systemInfo.machine
                          encoding:NSUTF8StringEncoding];
}

結果:

@"iPhone10,3" on iPhone X (CDMA)
@"iPhone10,6" on iPhone X (GSM)

この回答を参照しください。

完全なコード実装:

#import <sys/utsname.h>

NSString * GetDeviceModel(void)
{
    static dispatch_once_t onceToken;
    static NSString *strModelID = nil;

    dispatch_once(&onceToken, ^{
#if TARGET_IPHONE_SIMULATOR
        strModelID = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];
#else
        struct utsname systemInfo;

        uname(&systemInfo);
        strModelID = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
#endif
    });

    return strModelID;
}

// See the `Hardware strings` in https://en.wikipedia.org/wiki/List_of_iOS_devices
BOOL IsiPhoneX(void)
{
    NSString *strModelID = GetDeviceModel();

    return [strModelID isEqualToString:@"iPhone10,3"] || [strModelID isEqualToString:@"iPhone10,6"];
}

BOOL IsNotchiPhone(void)
{
    NSArray<NSString *> *notchiModels = @[
        @"iPhone10,3", @"iPhone10,6", // iPhone X
        @"iPhone11,2", @"iPhone11,4", @"iPhone11,6", // iPhone XS (Max)
        @"iPhone11,8", // iPhone XR
        @"iPhone12,1", @"iPhone12,3", @"iPhone12,5", // iPhone 11 (Pro (Max))
    ];

    return [notchiModels containsObject:GetDeviceModel()];
}

1
シミュレータを正しく処理するため、正解です。#import行を「完全なコード」セクションに追加してください。私は最初の試みでそれを見逃しました(コピー/貼り付け)。
mpoisot 2017年

1
それが私の好みの方法です。デバイスモデル文字列の完全なリストについては、このWikiを参照しください。サイドコメントとして、@ "iphone10,3"もハードコードと見なすことができます。
YvesLeBorg 2017年

1
@YvesLeBorgはい、それは本当に重要な論争の的になる問題です。ハードウェアモデル文字列には、デバイスのスクリーンポイントよりも一意の識別子があると思います。一般に、データ統計に使用されます。
イタチ

25
#define IS_IPHONE        (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS  (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_IPHONE_X      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)

IS_IPHONE_Xを定義します(IS_IPHONE && [[UIScreen mainScreen] bounds] .size.height == 812.0)

#define IS_IPHONE_XS      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
#define IS_IPHONE_X_MAX      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 896.0)
#define IS_RETINA        ([[UIScreen mainScreen] scale] >= 2.0) // 3.0 for iPhone X, 2.0 for others

#define IS_IPAD_DEVICE   [(NSString*)[UIDevice currentDevice].model hasPrefix:@"iPad"]

注:-注意してください、それは縦向きのみで正常に動作します


2
注意してください、それは縦向きでのみうまく機能します
CFIFok

1
これをありがとう。うまくいきます。横長モードでは、これらの数値を調整する必要があります。iPhoneXのランドスケープモードでのマジックナンバーは375.0
pvella

で使用nativeScaleしているiPhone Plus / Max / Proがいくつ3.0かありますよね?
イタチ

24

すべての答えを見た後、これは私がやったことです:

解決策(Swift 4.1互換)

extension UIDevice {
    static var isIphoneX: Bool {
        var modelIdentifier = ""
        if isSimulator {
            modelIdentifier = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
        } else {
            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            var machine = [CChar](repeating: 0, count: size)
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
            modelIdentifier = String(cString: machine)
        }

        return modelIdentifier == "iPhone10,3" || modelIdentifier == "iPhone10,6"
    }

    static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }
}

使用する

if UIDevice.isIphoneX {
    // is iPhoneX
} else {
    // is not iPhoneX
}

注意

Swift 4.1 以前では、アプリがシミュレーターで実行されているかどうかを確認できます。

TARGET_OS_SIMULATOR != 0

Swift 4.1以降では、ターゲット環境のプラットフォーム条件を使用して、アプリがシミュレーターで実行されているかどうかを確認できます

#if targetEnvironment(simulator)
    return true
#else
    return false
#endif

(古い方法はまだ機能しますが、この新しい方法はより将来の証明です)


これでリンゴは元気になりますか?
Surjeet Rajput

@ commando24はい、このコードのためにアプリを拒否する理由はわかりません。
Cloud9999Strife 2018年

18

寸法に基づくこれらすべての答えは、将来のデバイスでの不正な動作の影響を受けやすくなります。今日は機能しますが、来年同じサイズのiPhoneがあり、ガラスなどの下にカメラなどがあり、「ノッチ」がない場合はどうでしょうか。アプリを更新するしか選択肢がない場合、それはあなたとあなたの顧客にとって貧弱なソリューションです。

「iPhone10,1」のようなハードウェアモデル文字列を確認することもできますが、Appleが時々、世界中の異なるキャリアに対して異なるモデル番号をリリースするため、問題があります。

正しいアプローチは、上部のレイアウトを再設計するか、カスタムナビゲーションバーの高さで発生している問題を解決することです(これに焦点を当てます)。しかし、これらのいずれも行わないことに決めた場合、これを今日機能させるためのハッキングであることを理解し、ハッキングを維持するために、ある時点で(おそらく複数回)修正する必要があります。ワーキング。


1
正しい。Xが常にAであるという仮定を、Xが常にAになるという前提を、Bになる条件Yが深く掘り下げられない限り、常にAになります。アップルが指定した安全領域に基づいたサイズであり、二次的な推測ではありません。
トミー

2
次のiPhoneが実際に出たら心配になります。アプリを今すぐ機能させたい。
Vahid Amiri 2017

13

SWIFT 4+回答

iPhone X、XR、XS、XSMAX、11 Pro、11 Pro Max:

注:テストには実際のデバイスが必要

参照

 let deviceType = UIDevice.current.modelName
        switch deviceType {
        case "iPhone10,3", "iPhone10,6":
            print("iPhoneX")
        case "iPhone11,2":
            print("iPhone XS")
        case "iPhone11,4":
            print("iPhone XS Max")
        case "iPhone11,6":
            print("iPhone XS Max China")
        case "iPhone11,8":
            print("iPhone XR")
        case "iPhone12,3":
            print("iPhone 11 Pro")
        case "iPhone12,5":
            print("iPhone 11 Pro Max")
        default:
            break
}

extension UIDevice {
    var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        return identifier
    }
}

方法1の場合、funcの外にある「var window」プロパティを取り除き、その中に「let」定数を置くだけです(UIWindowタイプ、つまりオプションではありません)。起動時にself.view.windowがnilになる可能性があり、UIApplication.shared.keyWindowも同様にnilになる可能性があるので、この回答が気に入っています。
Rolleric 2017年

11

SWIFT 4/5再利用可能な拡張子を持つiPhone 11のサポート

    public extension UIDevice {

    public enum `Type` {
        case iPad
        case iPhone_unknown
        case iPhone_5_5S_5C
        case iPhone_6_6S_7_8
        case iPhone_6_6S_7_8_PLUS
        case iPhone_X_Xs
        case iPhone_Xs_11_Pro_Max
        case iPhone_Xr_11
        case iPhone_11_Pro
    }

    public var hasHomeButton: Bool {
        switch type {
        case .iPhone_X_Xs, .iPhone_Xr_11, .iPhone_Xs_11_Pro_Max, .iPhone_11_Pro:
            return false
        default:
            return true
        }
    }

    public var type: Type {
        if userInterfaceIdiom == .phone {
            switch UIScreen.main.nativeBounds.height {
            case 1136: return .iPhone_5_5S_5C
            case 1334: return .iPhone_6_6S_7_8
            case 1920, 2208: return .iPhone_6_6S_7_8_PLUS
            case 2436: return .iPhone_X_Xs
            case 2688: return .iPhone_Xs_11_Pro_Max
            case 1792: return .iPhone_Xr_11
            case 2426: return .iPhone_11_Pro
            default: return .iPhone_unknown
        }
        }
        return .iPad
   }
}

2
良い拡張子ですが、ここで最もUIDevice.current.hasHomeButton
役立つの

1
@ale_stroは、ユニバーサルアプリのデバイスを決定するためにuserInterfaceIdiomを使用するのは良いことですか?ほとんどの人はこれを推奨しません。それを使用することに害はありますか?
shaqirが2018

10

はい、可能です。UIDevice-Hardware拡張機能をダウンロード(またはCocoaPod 'UIDevice-Hardware'経由でインストール)して、次を使用します。

NSString* modelID = [[[UIDevice currentDevice] modelIdentifier];
BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"];

これはシミュレータでは機能せず、実際のデバイスでのみ機能することに注意してください。


ここにすべてのデバイスコード:iphonesoft.fr/2016/10/31/… 例:iPhone X:iPhone10,5およびiPhone10,6
Medhi

ウィキペディアハードウェア文字列は、「iPhone10,3およびiPhone10,6」と述べています。@Medhi
イタチ

@Medhi、ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIF‌​IER"]シミュレータで使用してXcodeから実際の値を取得できます。
・クール

9

@saswanbの応答によると、これはSwift 4バージョンです。

var iphoneX = false
if #available(iOS 11.0, *) {
    if ((UIApplication.shared.keyWindow?.safeAreaInsets.top)! > CGFloat(0.0)) {
        iphoneX = true
    }
}

ステータスバーも安全領域の外側と見なされます。したがって、これは誤検知を返します!20ポイント(ステータスバーの高さ)より高いはずです。これは、デバイスがiPhone Xs、R、またはXs Maxの場合もtrueを返します。
MQoder 2018年

コードkeyWindowは適切に機能しますが、注意してください。nilメインのビューコントローラーが呼び出されるまでviewDidAppear
Casey

9

私はそれがただのスイフトであることを知っていますがソリューションにいますが、誰かを助けることができるでしょう。

私はglobals.swiftすべてのプロジェクトで、常に追加することの1つはDeviceType、ユーザーのデバイスを簡単に検出することです。

struct ScreenSize {
  static let width = UIScreen.main.bounds.size.width
  static let height = UIScreen.main.bounds.size.height
  static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height)
  static let maxWH = max(ScreenSize.width, ScreenSize.height)
}

struct DeviceType {
  static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH < 568.0
  static let iPhone5orSE   = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 568.0
  static let iPhone678     = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 667.0
  static let iPhone678p    = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 736.0
  static let iPhoneX       = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 812.0
  static let iPhoneXRMax   = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 896.0
  static var hasNotch: Bool {
    return iPhoneX || iPhoneXRMax
  }
}

それを使用するには:

if DeviceType.hasNotch {
  print("This executes on all phones with a notch")
}

if DeviceType.iPhone678 {
  print("This executes on iPhones 6, 7 and 8")
}

LaunchImageプロジェクトで使用する場合は、サポートされているすべてのデバイス(XS Max、XRなど)に画像を追加してくださいUIScreen.main.bounds。そうしないと、適切な値が返されません。


1
Swiftを初めて使用する友人は、誰かが知らない場合に備えて、これを使用する方法を尋ねました… if DeviceType.iPhoneX { //do something for iPhone X notch }else{ // don’t do anything about notch }
Liam Bolling

5

を使用してheightいるすべての回答は、1つの理由でストーリーの半分にすぎません。あなたは、デバイスの向きがあるとき、そのようにチェックするつもりならlandscapeLeftまたはlandscapeRightので、チェックが失敗するheightとスワップアウトされますwidth

そのため、私のソリューションはSwift 4.0では次のようになります。

extension UIScreen {
    ///
    static var isPhoneX: Bool {
        let screenSize = UIScreen.main.bounds.size
        let width = screenSize.width
        let height = screenSize.height
        return min(width, height) == 375 && max(width, height) == 812
    }
}

代わりにnativeBoundsを使用してください
Leo

4

AppleがリリースするUINavigationBarの高さが異なる唯一のデバイスがiPhone Xであると想定しないでください。より一般的なソリューションを使用してこの問題を解決してみてください。バーを常にデフォルトの高さよりも20px大きくしたい場合は、コードでバーの高さを64px(44px + 20px)に設定する代わりに、20pxを追加する必要があります。


それでは、他にどのような解決策を提案する必要がありますか?
ステファンマティス2017

@xaphodより良い答えがあります。
・クール

4
struct ScreenSize {
    static let width = UIScreen.main.bounds.size.width
    static let height = UIScreen.main.bounds.size.height
    static let maxLength = max(ScreenSize.width, ScreenSize.height)
    static let minLength = min(ScreenSize.width, ScreenSize.height)
    static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height)
}

struct DeviceType {
    static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength < 568.0
    static let iPhone5orSE = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 568.0
    static let iPhone678 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 667.0
    static let iPhone678p = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 736.0
    static let iPhoneX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 812.0

    static let IS_IPAD              = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1024.0
    static let IS_IPAD_PRO          = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1366.0
}

4

Swift 3 + 4:

デバイスサイズのピクセル値は不要

//UIApplication+SafeArea.swift

extension UIApplication { 

    static var isDeviceWithSafeArea:Bool {

        if #available(iOS 11.0, *) {
            if let topPadding = shared.keyWindow?.safeAreaInsets.bottom,
                topPadding > 0 {
                return true
            }
        }

        return false
    }
}

例:

if UIApplication.isDeviceWithSafeArea {
     //e.g. change the frame size height of your UITabBar
}

3
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)

2
iPhone Xのデフォルト画像をアップロードすると、812が返されます。それまでは、iPhone 7のサイズが返されると思いますが、
わかり

3
- (BOOL)isIphoneX {
    if (@available(iOS 11.0, *)) {
        UIWindow *window = UIApplication.sharedApplication.keyWindow;
        CGFloat topPadding = window.safeAreaInsets.top;
        if(topPadding>0) {
            return YES;
        }
        else {
            return NO;
        }
    }
    else {
        return NO;
    }
}

1
ベストアンサー!デバイスサイズのピクセル値は必要ありません。
Peter Kreinz、2018年

3

通常、プログラマーは上または下に制約するためにそれを必要とするため、これらのメソッドは

static func extraTop() -> CGFloat {

    var top: CGFloat = 0

    if #available(iOS 11.0, *) {

        if let t = UIApplication.shared.keyWindow?.safeAreaInsets.top {
            top = t
        }
    }
    return top
}

static func extraBottom() -> CGFloat {

    var bottom: CGFloat = 0

    if #available(iOS 11.0, *) {

        if let b = UIApplication.shared.keyWindow?.safeAreaInsets.bottom {
            bottom = b
        }
    }
    return bottom
}

iPhone X以前の場合、これらのメソッドは0を返します。

iPhone Xの場合:44と34

次に、これらのエクストラを上部または下部の制約に追加します


3

ネイティブ境界の高さが2436pxではなく2001pxになっている場合(私のように)、iOS 11より前の古いSDK(Xcode 9ではなくXcode 8)でアプリをビルドしたためです。古いSDKでは、iOSは画面を端から端まで、「センサーノッチ」を超えて拡大するのではなく、iPhone Xで「ブラックボックス化」されたアプリを表示します。これにより画面サイズが小さくなり、そのため、このプロパティは2436ではなく2001を返します。

最も簡単な解決策は、デバイスの検出のみに関心がある場合は、両方のサイズを確認することです。このメソッドを使用してFaceIDを検出し、生体認証タイプを指定するENUM値を持たない古いXcode SDKでビルドしました。この状況では、画面の高さを使用したデバイスの検出は、Xcodeを更新せずにデバイスにFaceIDとTouchIDがあるかどうかを確認する最良の方法のように思われました。


3

他のソリューションが示唆しているように、画面のピクセルサイズを使用しないでください。これは、将来のデバイスで誤検知を引き起こす可能性があるため、好ましくありません。UIWindowがまだレンダリングされていない場合(AppDelegate)は機能せず、ランドスケープアプリでは機能せず、スケールが設定されているとシミュレータで失敗する可能性があります。

代わりに、この目的のためにマクロを作成しました。非常に簡単に使用でき、前述の問題を防ぐためにハードウェアフラグに依存しています。

編集:iPhoneX、iPhone XS、iPhoneXR、iPhoneXS Maxをサポートするように更新されました


使用するには:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}

うん、本当に。


大きい:

これをどこかにコピーして貼り付けてください。私は.hファイルの一番下を好みます @end

#import <sys/utsname.h>

#if TARGET_IPHONE_SIMULATOR
#define IS_SIMULATOR YES
#else
#define IS_SIMULATOR NO
#endif

#define IS_DEVICE_IPHONEX (\
(^BOOL (void){\
NSString *__modelIdentifier;\
if (IS_SIMULATOR) {\
__modelIdentifier = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];\
} else {\
struct utsname __systemInfo;\
uname(&__systemInfo);\
__modelIdentifier = [NSString stringWithCString:__systemInfo.machine encoding:NSUTF8StringEncoding];\
}\
NSString *__iPhoneX_GSM_Identifier = @"iPhone10,6";\
NSString *__iPhoneX_CDMA_Identifier = @"iPhone10,3";\
NSString *__iPhoneXR_Identifier = @"iPhone11,8";\
NSString *__iPhoneXS_Identifier = @"iPhone11,2";\
NSString *__iPhoneXSMax_China_Identifier = @"iPhone11,6";\
NSString *__iPhoneXSMax_Other_Identifier = @"iPhone11,4";\
return ([__modelIdentifier isEqualToString:__iPhoneX_GSM_Identifier] || [__modelIdentifier isEqualToString:__iPhoneX_CDMA_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXR_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXS_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_China_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_Other_Identifier]);\
})()\
)

iPhoneXを検出した理由は、画面上部の切り欠きを回避するためだけです。もしそうなら、safeArea.topをチェックして、上記のノッチのサイズを検出できます。ちょうどことを確認してくださいあなたはUIWindowが読み込まれた後、それを測定そうではないのviewDidLoad中が、1つのスレッドサイクル後:if (@available(iOS 11.0, *)) { [UIApplication sharedApplication].keyWindow.safeAreaInsets.top }
アルバート・レンショウ

2

私はあなたの答えを詳しく説明し、UIDeviceをすばやく拡張しました。私は迅速な列挙型と「すべてが順番に」そしてアトマイズされるのが好きです。デバイスとシミュレータの両方で機能するソリューションを作成しました。

利点:-シンプルなインターフェース、使用例UIDevice.current.isIPhoneX -UIDeviceModelType列挙型はあなたに簡単に例えばcornerRadius、アプリで使用したいというモデル固有の機能と定数を拡張する機能を提供します

短所:-これはモデル固有の解決策であり、解像度固有ではありません-たとえば、Appleが同じ仕様の別のモデルを作成する場合、これは正しく機能せず、これを機能させるために別のモデルを追加する必要があります=>更新する必要がありますアプリ。

extension UIDevice {

    enum UIDeviceModelType : Equatable {

        ///iPhoneX
        case iPhoneX

        ///Other models
        case other(model: String)

        static func type(from model: String) -> UIDeviceModelType {
            switch model {
            case "iPhone10,3", "iPhone10,6":
                return .iPhoneX
            default:
                return .other(model: model)
            }
        }

        static func ==(lhs: UIDeviceModelType, rhs: UIDeviceModelType) -> Bool {
            switch (lhs, rhs) {
            case (.iPhoneX, .iPhoneX):
                return true
            case (.other(let modelOne), .other(let modelTwo)):
                return modelOne == modelTwo
            default:
                return false
            }
        }
    }

    var simulatorModel: String? {
        guard TARGET_OS_SIMULATOR != 0 else {
            return nil
        }

        return ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"]
    }

    var hardwareModel: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let model = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }

        return model
    }

    var modelType: UIDeviceModelType {
        let model = self.simulatorModel ?? self.hardwareModel
        return UIDeviceModelType.type(from: model)
    }

    var isIPhoneX: Bool {
        return modelType == .iPhoneX
    }
}

を使用する代わりに、Cloud9999Strifeの回答(および私の回答でも)のMirrorように使用する方が速くなりますsysctlbyname
2018

2

ステータスバーフレームの高さを利用して、iPhone Xかどうかを検出します。

if UIApplication.shared.statusBarFrame.height >= CGFloat(44) {
    // It is an iPhone X
}

これは、アプリケーションの縦向きではありません。デバイスの向きに応じてサイズを確認することもできます。また、他のiPhoneでは、ステータスバーが非表示になっている可能性があるため、フレームの高さは0です。iPhone Xでは、ステータスバーが非表示になることはありません。


あなたにはiPhoneXステータスバーを非表示にすることができますcontrollerこれに: - (BOOL)prefersStatusBarHidden { return YES; } 次にステータスバーの高さは0です
无夜之星辰

@無夜之星辰起動時にAppDelegateで確認します。
Tiois、2018年

2

私はPeter Kreinzのコードを使用していました(それがクリーンで必要なことをしたため)、それからデバイスが縦向きのときにだけ機能することに気付きました(トップのパディングが上になるので、明らかに)すべてを処理する拡張機能を作成しました画面サイズを中継せずに、それぞれのパディングがある方向:

extension UIDevice {

    var isIphoneX: Bool {
        if #available(iOS 11.0, *), isIphone {
            if isLandscape {
                if let leftPadding = UIApplication.shared.keyWindow?.safeAreaInsets.left, leftPadding > 0 {
                    return true
                }
                if let rightPadding = UIApplication.shared.keyWindow?.safeAreaInsets.right, rightPadding > 0 {
                    return true
                }
            } else {
                if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 0 {
                    return true
                }
                if let bottomPadding = UIApplication.shared.keyWindow?.safeAreaInsets.bottom, bottomPadding > 0 {
                    return true
                }
            }
        }
        return false
    }

    var isLandscape: Bool {
        return UIDeviceOrientationIsLandscape(orientation) || UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation)
    }

    var isPortrait: Bool {
        return UIDeviceOrientationIsPortrait(orientation) || UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
    }

    var isIphone: Bool {
        return self.userInterfaceIdiom == .phone
    }

    var isIpad: Bool {
        return self.userInterfaceIdiom == .pad
    }
}

そして、あなたの呼び出しサイトであなたはちょうど:

let res = UIDevice.current.isIphoneX

2

または、「DeviceKit」ポッドをチェックアウトすることもできます。インストール後、デバイスを確認するために必要なことは次のとおりです。

import DeviceKit
let device = Device()
if device == .iPhoneX {
  // place your code here
}

2

2019年11月:

これが、すべての制作プロジェクトで使用するものです。この要点はかなり長いことに注意してください。

  1. これは、幅や高さの計算を使用しませんが、次のことを行います。
  2. デバイス文字列モデルをチェックします。
  3. プライベート/ドキュメント化されていないAPIを使用しているため、ビルドがAppleに拒否されるリスクはありません。
  4. シミュレータで動作します💯

    import UIKit
    
    class DeviceUtility {
        /// Determines if the current device of the user is an iPhoneX type/variant.
        static var isIphoneXType: Bool {
            get {
                switch UIDevice().type {
                case .iPhoneXR, .iPhoneXS, .iPhoneXSMax, .iPhoneX, .iPhone11, .iPhone11Pro, .iPhone11ProMax: return true
                default: return false
                }
            }
        }
    }
    
    
    public enum DeviceModel : String {
        case simulator     = "simulator/sandbox",
    
        // MARK: - iPods
    
        iPod1              = "iPod 1",
        iPod2              = "iPod 2",
        iPod3              = "iPod 3",
        iPod4              = "iPod 4",
        iPod5              = "iPod 5",
    
        // MARK: - iPads
    
        iPad2              = "iPad 2",
        iPad3              = "iPad 3",
        iPad4              = "iPad 4",
        iPadAir            = "iPad Air ",
        iPadAir2           = "iPad Air 2",
        iPad5              = "iPad 5", //aka iPad 2017
        iPad6              = "iPad 6", //aka iPad 2018
    
        // MARK: - iPad Minis
    
        iPadMini           = "iPad Mini",
        iPadMini2          = "iPad Mini 2",
        iPadMini3          = "iPad Mini 3",
        iPadMini4          = "iPad Mini 4",
    
        // MARK: - iPad Pros
    
        iPadPro9_7         = "iPad Pro 9.7\"",
        iPadPro10_5        = "iPad Pro 10.5\"",
        iPadPro12_9        = "iPad Pro 12.9\"",
        iPadPro2_12_9      = "iPad Pro 2 12.9\"",
    
        // MARK: - iPhones
    
        iPhone4            = "iPhone 4",
        iPhone4S           = "iPhone 4S",
        iPhone5            = "iPhone 5",
        iPhone5S           = "iPhone 5S",
        iPhone5C           = "iPhone 5C",
        iPhone6            = "iPhone 6",
        iPhone6plus        = "iPhone 6 Plus",
        iPhone6S           = "iPhone 6S",
        iPhone6Splus       = "iPhone 6S Plus",
        iPhoneSE           = "iPhone SE",
        iPhone7            = "iPhone 7",
        iPhone7plus        = "iPhone 7 Plus",
        iPhone8            = "iPhone 8",
        iPhone8plus        = "iPhone 8 Plus",
        iPhoneX            = "iPhone X",
        iPhoneXS           = "iPhone XS",
        iPhoneXSMax        = "iPhone XS Max",
        iPhoneXR           = "iPhone XR",
        iPhone11           = "iPhone 11",
        iPhone11Pro        = "iPhone 11 Pro",
        iPhone11ProMax     = "iPhone 11 Pro Max",
    
        // MARK: - Apple TVs
    
        AppleTV            = "Apple TV",
        AppleTV_4K         = "Apple TV 4K",
    
        // MARK: - Unrecognized
    
        unrecognized       = "?unrecognized?"
    }
    
    // #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    //MARK: UIDevice extensions
    // #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    
    public extension UIDevice {
        var type: DeviceModel {
            var systemInfo = utsname()
            uname(&systemInfo)
            let modelCode = withUnsafePointer(to: &systemInfo.machine) {
                $0.withMemoryRebound(to: CChar.self, capacity: 1) {
                    ptr in String.init(validatingUTF8: ptr)
    
                }
            }
            let modelMap : [ String : DeviceModel ] = [
    
                // MARK: - Simulators
    
                "i386"      : .simulator,
                "x86_64"    : .simulator,
    
                // MARK: - iPod
    
                "iPod1,1"   : .iPod1,
                "iPod2,1"   : .iPod2,
                "iPod3,1"   : .iPod3,
                "iPod4,1"   : .iPod4,
                "iPod5,1"   : .iPod5,
    
                // MARK: - iPad
    
                "iPad2,1"   : .iPad2,
                "iPad2,2"   : .iPad2,
                "iPad2,3"   : .iPad2,
                "iPad2,4"   : .iPad2,
                "iPad3,1"   : .iPad3,
                "iPad3,2"   : .iPad3,
                "iPad3,3"   : .iPad3,
                "iPad3,4"   : .iPad4,
                "iPad3,5"   : .iPad4,
                "iPad3,6"   : .iPad4,
                "iPad4,1"   : .iPadAir,
                "iPad4,2"   : .iPadAir,
                "iPad4,3"   : .iPadAir,
                "iPad5,3"   : .iPadAir2,
                "iPad5,4"   : .iPadAir2,
                "iPad6,11"  : .iPad5, //aka iPad 2017
                "iPad6,12"  : .iPad5,
                "iPad7,5"   : .iPad6, //aka iPad 2018
                "iPad7,6"   : .iPad6,
    
                // MARK: - iPad mini
    
                "iPad2,5"   : .iPadMini,
                "iPad2,6"   : .iPadMini,
                "iPad2,7"   : .iPadMini,
                "iPad4,4"   : .iPadMini2,
                "iPad4,5"   : .iPadMini2,
                "iPad4,6"   : .iPadMini2,
                "iPad4,7"   : .iPadMini3,
                "iPad4,8"   : .iPadMini3,
                "iPad4,9"   : .iPadMini3,
                "iPad5,1"   : .iPadMini4,
                "iPad5,2"   : .iPadMini4,
    
                // MARK: - iPad pro
    
                "iPad6,3"   : .iPadPro9_7,
                "iPad6,4"   : .iPadPro9_7,
                "iPad7,3"   : .iPadPro10_5,
                "iPad7,4"   : .iPadPro10_5,
                "iPad6,7"   : .iPadPro12_9,
                "iPad6,8"   : .iPadPro12_9,
                "iPad7,1"   : .iPadPro2_12_9,
                "iPad7,2"   : .iPadPro2_12_9,
    
                // MARK: - iPhone
    
                "iPhone3,1" : .iPhone4,
                "iPhone3,2" : .iPhone4,
                "iPhone3,3" : .iPhone4,
                "iPhone4,1" : .iPhone4S,
                "iPhone5,1" : .iPhone5,
                "iPhone5,2" : .iPhone5,
                "iPhone5,3" : .iPhone5C,
                "iPhone5,4" : .iPhone5C,
                "iPhone6,1" : .iPhone5S,
                "iPhone6,2" : .iPhone5S,
                "iPhone7,1" : .iPhone6plus,
                "iPhone7,2" : .iPhone6,
                "iPhone8,1" : .iPhone6S,
                "iPhone8,2" : .iPhone6Splus,
                "iPhone8,4" : .iPhoneSE,
                "iPhone9,1" : .iPhone7,
                "iPhone9,3" : .iPhone7,
                "iPhone9,2" : .iPhone7plus,
                "iPhone9,4" : .iPhone7plus,
                "iPhone10,1" : .iPhone8,
                "iPhone10,4" : .iPhone8,
                "iPhone10,2" : .iPhone8plus,
                "iPhone10,5" : .iPhone8plus,
                "iPhone10,3" : .iPhoneX,
                "iPhone10,6" : .iPhoneX,
                "iPhone11,2" : .iPhoneXS,
                "iPhone11,4" : .iPhoneXSMax,
                "iPhone11,6" : .iPhoneXSMax,
                "iPhone11,8" : .iPhoneXR,
                "iPhone12,1" : .iPhone11,
                "iPhone12,3" : .iPhone11Pro,
                "iPhone12,5" : .iPhone11ProMax,
    
                // MARK: - AppleTV
    
                "AppleTV5,3" : .AppleTV,
                "AppleTV6,2" : .AppleTV_4K
            ]
    
            if let model = modelMap[String.init(validatingUTF8: modelCode!)!] {
                if model == .simulator {
                    if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
                        if let simModel = modelMap[String.init(validatingUTF8: simModelCode)!] {
                            return simModel
                        }
                    }
                }
                return model
            }
            return DeviceModel.unrecognized
        }
    }

使用法:let inset:CGFloat = DeviceUtility.isIphoneXType?50.0:40.0


完璧に動作します。ありがとう。SwiftUIプロジェクトで使用しています。
LondonGuy

1

私は同じ問題を最近解決しなければなりませんでした。そして、この質問は明確に回答されていますが(「いいえ」)、これはiPhone X固有のレイアウト動作を必要とする他の人を助けるかもしれません。

デバイスがiPhone Xであるかどうかにはあまり興味がありませんでした。デバイスにノッチ付きディスプレイがあるかどうかには興味がありました。

private static var hasNotchedDisplay: Bool {
    if let window = UIApplication.shared.keyWindow {
        return (window.compatibleSafeAreaInsets.top > 20.0 || window.compatibleSafeAreaInsets.left > 0.0 || window.compatibleSafeAreaInsets.right > 0.0)
    }

    return false
}

hasOnScreenHomeIndicator同じ行に沿って変数を書き込むこともできます(ただし、安全領域の下部を確認してください)。

上記では、UIViewiOS 10以前のセーフエリアインセットに簡単にアクセスできるように、私の拡張機能をオンにしています。

@objc public extension UIView {
    @objc public var compatibleSafeAreaInsets: UIEdgeInsets {
        if #available(iOS 11.0, *) {
            return safeAreaInsets
        } else {
            return .zero
        }
    }

    @objc public var compatibleSafeAreaLayoutGuide: UILayoutGuide {
        if #available(iOS 11.0, *) {
            return safeAreaLayoutGuide
        } else {
            return layoutMarginsGuide
        }
    }
}

1

縦画面専用私がチェックするために、ビューのフレームの幅と高さを使用します。

override func viewDidLoad() {
    super.viewDidLoad()

    // iPhone Xr: -414 x 896
    // iPhone Xs Max: -414 x 896
    // iPhone X, Xs: -375 x 812

    if view.frame.width == 414 && view.frame.height == 896 || view.frame.width == 375 && view.frame.height == 812  {

        print("iPhone X")
    } else {

        print("not iPhone X")
    }

}

縦向きの画面の寸法はここにリストされています

ここに画像の説明を入力してください


0

デバイスが何であるかを知りたい理由はいくつかあります。

  1. デバイスの高さ(および幅)を確認できます。これはレイアウトに役立ちますが、正確なデバイスを知りたいのであれば、通常はそうしたくないでしょう。

  2. レイアウトの目的で、を使用することもできますUIView.safeAreaInsets

  3. たとえば、診断のために電子メールに含めるためにデバイス名を表示したい場合は、を使用してデバイスモデルを取得した後sysctl ()、これに相当するものを使用して名前を把握できます。

    $ curl http://appledevicenames.com/devices/iPhone10,6
    
    iPhone X
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.