以编程方式识别带有 Notch 的 iPhone

Identify iPhones with Notch Programmatically

我正在尝试以编程方式识别带有缺口的 iPhones。我知道 screen.size 方法,但是当你有一个支持所有界面方向的通用应用程序时,它就会变得一团糟(计算所有可能的变化)。所以我正在寻找一种更简单、更优雅的方法来检测更新的 iPhones X 模型。

我在网上偶然发现了一个应该有效的方法。在其中,您测量安全区域的底部插图,如果它不为零,则您有一个 iPhone X 模型。这在理论上是有道理的,因为安全区域在 iPhone X 手机上不会到达屏幕底部,但在所有其他设备上都会。我是这样检查的:

if (@available( iOS 11.0, * )) {
    if ([[[UIApplication sharedApplication] keyWindow] safeAreaInsets].bottom > 0) {
        // iPhone with notch
    }
} else {
    // Regular iPhone
}

但是,这不起作用。有人可以指出我在实施中的错误或确认此方法是否可行吗?

我不得不四处挖掘,但找到了答案(我想向 user6788419 大喊大叫,他的正确答案深埋在另一个线程中)。

首先,上面的代码是正确的。检查安全区域的底部插图是否大于零将准确识别带有缺口的 iPhone(截至撰写本文时)。所以,这是正确的:

if (@available( iOS 11.0, * )) {
    if ([[[UIApplication sharedApplication] keyWindow] safeAreaInsets].bottom > 0) {
        // iPhone with notch
    }
}

但是,在代码中放置上述语句的位置很重要,因为 UIWindow 在第一个 运行 循环结束之前不可用。这意味着,如果您在 viewDidLoad 中或结束之前检查缺口(例如在您的 init 中),底部插图将始终为零。

如果你和我一样,需要这个检查来设置你的主视图,你可以将所有设置移动到单独的函数(例如 postViewDidLoad)并在 viewDidLoad 结束后调用它:

[self performSelector:@selector(postViewDidLoad) withObject:nil afterDelay:0.0f];

或者,您也可以将其附上:

dispatch_async(dispatch_get_main_queue(), ^{
    // Check notch here
});

更新:iOS 13 及以上的代码(做同样的事情)。当您调用该函数时,“areaPosition”是一个字符串参数。 “顶部”检查缺口,其他所有检查是否存在底部主页指示器。

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

- (BOOL) checkSafeArea:(NSString *)areaPosition {
   if (@available(iOS 13.0, *)) {
       if ([areaPosition isEqualToString:@"top"]) {
           return [self keyWindow].safeAreaInsets.top > 20.0f;
       } else {
           return [self keyWindow].safeAreaInsets.bottom > 0.0f;
       }
   } else {
       if ([areaPosition isEqualToString:@"top"]) {
           return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0f;
       } else {
           return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.bottom > 0.0f;
       }
   }
   return  NO;
}

更新 Swift 5 和 iOS14

这解决了 keyWindow 弃用警告。

var hasNotch: Bool {
       
 let bottom = UIApplication.shared.windows.first{ [=10=].isKeyWindow }?.safeAreaInsets.bottom ?? 0
 return bottom > 0
           
    }

Swift 5 和(iOS12 或以上)

var isNotch: Bool {
   return (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) > 0
}