我的iOS应用程序使用了UINavigationBar的自定义高度,这导致新iPhone X出现了一些问题.

是否有人已经知道如何通过编程(在Objective-C中)检测应用程序是否在iPhone X上运行?

EDIT:

当然,判断屏幕的大小也是可能的,不过,我想知道是否有像TARGET_OS_IPHONE这样的"内置"方法来检测iOS……

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    if (screenSize.height == 812)
        NSLog(@"iPhone X");
}

EDIT 2:

我不认为我的问题与相关问题重复.当然,有一些方法可以"测量"当前设备的不同属性,并使用结果来决定使用哪个设备.然而,正如我在第一次编辑中试图强调的那样,这并不是我问题的真正重点.

实际问题是:"Is it possible to directly detect if the current device is an iPhone X (e.g. by some SDK feature) or do I have to use indirect measurements"

根据目前的答案,我假设答案是"不,没有直接的方法.测量是可行的".

推荐答案

根据你的问题,答案是否定的.没有直接的方法.有关更多信息,请访问此处:

iPhone X的高度是2436像素

From Device Screen Sizes 和 resolutions:

enter image description here

From Device Screen Sizes 和 Orientations:

enter image description here

Swift 3 和 later:

if UIDevice().userInterfaceIdiom == .phone {
    switch UIScreen.main.nativeBounds.height {
        case 1136:
            print("iPhone 5 or 5S or 5C")
        
        case 1334:
            print("iPhone 6/6S/7/8")
        
        case 1920, 2208:
            print("iPhone 6+/6S+/7+/8+")
        
        case 2436:
            print("iPhone X/XS/11 Pro")
        
        case 2688:
            print("iPhone XS Max/11 Pro Max")
        
        case 1792:
            print("iPhone XR/ 11 ")
        
        default:
            print("Unknown")
        }
    }

Objective-C:

if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        switch ((int)[[UIScreen mainScreen] nativeBounds].size.height) {
            case 1136:
                printf("iPhone 5 or 5S or 5C");
                    break;

            case 1334:
                printf("iPhone 6/6S/7/8");
                break;

            case 1920:
            case 2208:
                printf("iPhone 6+/6S+/7+/8+");
                break;

           case 2436:
                printf("iPhone X/XS/11 Pro");
                 break;

            case 2688:
                printf("iPhone XS Max/11 Pro Max");
                 break;

            case 1792:
                printf("iPhone XR/ 11 ");
                 break;

            default:
                printf("Unknown");
                break;
        }
    }

Xamarin.iOS:

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) {
    if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1136) {
        Console.WriteLine("iPhone 5 or 5S or 5C");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1334) {
        Console.WriteLine("iPhone 6/6S/7/8");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1920 || (UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2208) {
        Console.WriteLine("iPhone 6+/6S+/7+/8+");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2436) {
        Console.WriteLine("iPhone X, XS, 11 Pro");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2688) {
        Console.WriteLine("iPhone XS Max, 11 Pro Max");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1792) {
        Console.WriteLine("iPhone XR, 11");
    } else {
        Console.WriteLine("Unknown");
    }
}

根据您的问题,如下所示:

或者使用screenSize.height作为浮点型812.0f,而不是整型812.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
        // 812.0 on iPhone X, XS
        // 896.0 on iPhone XS Max, XR.

    if (screenSize.height >= 812.0f)
        NSLog(@"iPhone X");
    }

有关更多信息,请参阅iOS人机界面指南中的以下页面:

Swift:

topNotch检测:

If anyone considering using notch to detect iPhoneX, mind that on "l和scape" its same for all iPhones.

var hasTopNotch: Bool {
    if #available(iOS 13.0,  *) {
        return UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.safeAreaInsets.top ?? 0 > 20
    }else{
     return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }

    return false
}

Objective-C:

- (BOOL)hasTopNotch {
   if (@available(iOS 13.0, *)) {
       return [self keyWindow].safeAreaInsets.top > 20.0;
   }else{
       return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0;
   }
   return  NO;
}

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

UPDATE:

不要使用userInterfaceIdiom属性来标识设备类型,如documentation for userInterfaceIdiom所述:

For universal applications, you can use this property to tailor the behavior of your application for a specific type of device. For example, iPhone 和 iPad devices have different screen sizes, so you might want to create different views 和 controls based on the type of the current device.

也就是说,此属性仅用于标识正在运行的应用程序的视图样式.然而,iPhone应用程序(不是通用的)可以通过应用程序store 安装在iPad设备上,在这种情况下,userInterfaceIdiom也会返回UIUserInterfaceIdiomPhone.

正确的方法是通过uname获取机器名称.有关详细信息,请查看以下内容:

Ios相关问答推荐

Xcode版本15.2上未显示iOS 16.4的模拟器

验证开发人员应用程序证书是否已在您的设备上验证

UIAlertController的空子类是否可以与`appearance(whenContainedInInstancesOf:)`一起安全使用

Flutter应用内购买无法恢复购买

使用异步重载实现Swift协议一致性

Swift Combine和iOS版本限制?

@Query与SwiftData数据列表绑定

如何擦除 Swift 中的 Core Graphics Context 绘图?

SwiftUI:同时拖动父视图和子视图,但手指分开

在 Swift 中映射 MySQL 数据

如何为视图的 colored颜色 和宽度设置动画?

从远程通知启动时,iOS 应用程序加载错误

向左或向右移动时如何水平翻转sprite?

无法同时满足约束 - 没有适当的约束

如何使用 swift 显示 .svg 图像

如何在 SwiftUI 中检测 TextField 的实时变化?

获取 iOS 上所有联系人的列表

从故事板导航到其他 Swift 1.2 文件时 Xcode 6.3 崩溃

UIView - 加载视图时如何获得通知?

使用 xib 创建可重用的 UIView(并从情节提要中加载)