以编程方式识别带有刘海的iPhone

10

我正在尝试以编程方式识别有刘海的iPhone型号。我知道screen.size方法,但是当您拥有一个支持所有界面方向的通用应用程序时,这会变得一团糟(计算所有可能的变化)。因此,我正在寻找一种更简单和更优雅的方法来检测新的iPhone X型号。

我在网上偶然发现了一种被认为有效的方法。在其中,您测量安全区域的底部插图,如果不为零,则有一个iPhone X型号。理论上这是有意义的,因为安全区域在iPhone X手机上没有达到屏幕底部,但在所有其他设备上都有。我通过以下方式进行检查:

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

然而,这并不起作用。有人可以指出我在实现中的错误或确认这种方法是否可行吗?


3
你为什么要检测刘海屏?其实并不需要这样做。使用适当的约束条件,一切都会按预期运行。 - rmaddy
只需翻译此内容:https://medium.com/@cafielo/how-to-detect-notch-screen-in-swift-56271827625d - Karlo A. López
@KarloA.López,这就是您在上面看到的内容...安全区域插图的底部始终为0(无论手机是否有缺口);因此,要么链接的解决方案不再有效,要么我犯了一个错误。 我正在尝试找出哪个可能会找到解决方案。 - Gergely Kovacs
3个回答

12

我不得不费些功夫查找,但最终找到了答案(我想向用户6788419大喊一声,他正确的答案被深埋在另一个线程中)。

首先,上面的代码是正确的。检查安全区域底部插入是否大于零将准确地识别带有刘海的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”是一个字符串参数。“top”检查缺口,其他所有内容都检查底部主页指示器的存在。

- (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;
}

嗨Gergely,我在IOS13中使用keywindow时收到了弃用警告,你知道解决这个问题的方法吗? - Mathias
无法在 iPhone 13 Pro Max 上正常工作。 - kanso
我已经添加了一段更近期的代码,可以在当前设备上运行。 - Gergely Kovacs

3

已更新至 Swift 5 和 iOS 14。

此解决方案解决了关于 keyWindow 废弃警告的问题。

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

3

Swift 5 和 (iOS12 或以上)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接