黒毛和牛モモバラ切り落し100g298円

iPhoneアプリを作ってます。リリースノートとか用ブログです。

iPhone XS 等を含む iPhoneX 系列か否かの判定

ラノベルで iPhoneX か否かで処理の分岐が結構あるのですが、iPhone XS 等の発売に合わせてメンテするのを忘れてまして、バグってたので以下のように修正しました。

// UIDevice+Model.h

#import <UIKit/UIKit.h>

@interface UIDevice (Model)

- (BOOL)isIPhoneX;

@end

以下で dispatch_once してるのは気分です。

// UIDevice+Model.m

#import "UIDevice+Model.h"
#import <sys/utsname.h>

static NSString *
modelID()
{
    // Pods に https://github.com/erichoracek/UIDevice-Hardware とかがあるんだけど、
    // シミュレータ対応してなかったので自前で
#if TARGET_IPHONE_SIMULATOR
    NSString *model = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];
#else
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *model = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
#endif
    return model;
}

@implementation UIDevice (Model)

- (BOOL)isIPhoneX
{
    static BOOL _isIPhoneX = NO;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *model = modelID();
        if (![model hasPrefix:@"iPhone"]) {
            _isIPhoneX = NO;
            return;
        }
        NSString *s = [model substringFromIndex:6];
        NSInteger version = [s integerValue];
        if (version == 10) {
            // iPhone8 が iPhone10,4
            _isIPhoneX = [model isEqualToString:@"iPhone10,3"] || [model isEqualToString:@"iPhone10,6"];
        } else if (version > 10) {
            _isIPhoneX = YES;
        } else {
            _isIPhoneX = NO;
        }
    });
    return _isIPhoneX;
}

@end