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カテゴリ
@import UIKit;
@interface UIDevice (Extension)
+ (BOOL)is_iPhoneX;
@end
GCDを用いて初回1度だけ判定してstatic変数に格納しています。
#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が含まれる変数や関数をキャメルケースでつなげるとき悩みますね。
使う時
#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))
参考: 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.scale
とUIScreen.mainScreen.nativeScale
の値が違っていたらDisplay Zoomモードであると判断できます。scale
ではなくnativeScale
の方が変化します。
if (UIScreen.main.scale != UIScreen.main.nativeScale) {
// display zoom mode
}
if (UIScreen.mainScreen.scale != UIScreen.mainScreen.nativeScale) {
// display zoom mode
}