以编程方式识别带有 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
}
我正在尝试以编程方式识别带有缺口的 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
}