Objective-C
iPhone
iOS
AutoLayout

iPhoneXだけSafeAreaLayoutGuideにConstraintsを貼るようにした

More than 1 year has passed since last update.

そうです。ゴリ押しです。

iPhoneXの発表を受けてDeveloperの皆様方いかがお過ごしでしょうか。

私はstoryboardにsafeAreaLayoutGuideが追加されて、「ほーステータスバーとか出していく方針なのか」「まぁフルスクリーンだし無視して潜り込ませていこうか」とタカをくくっていたところXcode9 GM Seedまでひた隠しにされたiPhoneXにしてやられた形です。なんですかあの切欠きは。

そう、SafeAreaLayoutGuide。使って楽したいですよね。でもstoryboardに要件があるんです。
DeployTarget >= 9.0なんです。
ビジネス要件で9.0未満をサポートするパターンが苦境に立たされてます。Appleの圧力というやつです。

また、storyboardを使用する場合だとiPhone8ではフルスクリーン、iPhoneXではsafeAreaの範囲内、といった切り替えは手軽にできそうにないですね。その場合も、下記のようなコードベースで制約を貼り分けることで解決できるんじゃないかと思います。

前提

  • コードベースでAutoLayoutを使用する

結論

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad]

    // フルスクリーンで表示するView
    UIView *fullScreenView = [UIView new];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    view.backgroundColor = [UIColor greenColor];
    [self.view addSubView: fullScreenView];

    id relateBase = self.view;
    // iPhoneXだけsafeAreaLayoutGuideを使用したい
    // iPhoneXはiOS11以上が確定のはずなので、iOSバージョンチェックはいささか冗長
    NSArray<NSString*> *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    if ([versionCompatibility[0] intValue] >= 11 ) {
        // ゴリ押しiPhoneX対応
        CGSize  screenSize = [UIScreen mainScreen].bounds.size;
        CGFloat shortDistance = (screenSize.width < screenSize.height)? screenSize.width:  screenSize.height;
        CGFloat longDistance  = (screenSize.width < screenSize.height)? screenSize.height: screenSize.width;
        CGSize portraitScreenSize = CGSizeMake(shortDistance, longDistance);
        CGSize iphoneXscreenSize  = CGSizeMake(375.0, 812.0);
        if (CGSizeEqualToSize(portraitScreenSize, iphoneXscreenSize)) {
            relateBase = view.safeAreaLayoutGuide;
        }
    }

    [target setTranslatesAutoresizingMaskIntoConstraints:NO];
    [view addConstraints:@[
        [NSLayoutConstraint constraintWithItem:fullScreenView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:relateBase attribute:NSLayoutAttributeTop multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:fullScreenView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:relateBase attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:relateBase attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:fullScreenView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:relateBase attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:fullScreenView attribute:NSLayoutAttributeLeading multiplier:1 constant:0],
    ]];    
}
@end

main Screenのサイズでゴリ押し。

hardware stringを基準にするとiOSシミュレーター時点で確認できないので手法から除外。