我的iOS应用程序为UINavigationBar使用了自定义高度,这在新的iPhone X上导致了一些问题。

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

编辑:

当然,检查屏幕的大小是可能的,但是,我想知道是否有一些“内置”的方法,如TARGET_OS_IPHONE来检测iOS…

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

编辑2:

我不认为,我的问题是一个重复的关联问题。当然,有一些方法可以“测量”当前设备的不同属性,并使用结果来决定使用哪种设备。然而,这并不是我在第一篇编辑中试图强调的问题的实际意义。

真正的问题是:“是否有可能直接检测当前设备是否是iPhone X(例如通过某些SDK功能),还是我必须使用间接测量?”

根据目前给出的答案,我假设答案是“不,没有直接的方法。测量是要走的路。”


当前回答

下面是Objective-C中需要的两个宏。

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 24.0)

用法:

if (IS_IPHONE_X) {
}

我希望它能帮助别人。

其他回答

是的,这是可能的。 下载UIDevice-Hardware扩展(或通过CocoaPod 'UIDevice-Hardware'安装),然后使用:

NSString* modelID = [[[UIDevice currentDevice] modelIdentifier];
BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"];

注意,这不能在模拟器中工作,只能在实际设备上工作。

我知道这只是一个快速的解决方案,但它可以帮助一些人。

我在每个项目中都有global .swift,有一些代码来简化我的生活,我总是添加的一件事是ScreenSize和hasNotch,可以轻松检测手机类型和尺寸:

struct ScreenSize {
  static let width = UIScreen.main.bounds.size.width
  static let height = UIScreen.main.bounds.size.height
}

var hasNotch: Bool {
  return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 0
}

然后使用它:

if hasNotch {
  print("This executes on all phones with a notch")
}
- (BOOL)isIphoneX {
    if (@available(iOS 11.0, *)) {
        UIWindow *window = UIApplication.sharedApplication.keyWindow;
        CGFloat topPadding = window.safeAreaInsets.top;
        if(topPadding>0) {
            return YES;
        }
        else {
            return NO;
        }
    }
    else {
        return NO;
    }
}

在看完所有的答案后,我最后是这么做的:

解决方案(兼容Swift 4.1)

extension UIDevice {
    static var isIphoneX: Bool {
        var modelIdentifier = ""
        if isSimulator {
            modelIdentifier = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
        } else {
            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            var machine = [CChar](repeating: 0, count: size)
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
            modelIdentifier = String(cString: machine)
        }

        return modelIdentifier == "iPhone10,3" || modelIdentifier == "iPhone10,6"
    }

    static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }
}

Use

if UIDevice.isIphoneX {
    // is iPhoneX
} else {
    // is not iPhoneX
}

Note

Pre Swift 4.1你可以检查应用程序是否在模拟器上运行,就像这样:

TARGET_OS_SIMULATOR != 0

从Swift 4.1开始,你可以使用目标环境平台条件检查应用程序是否在模拟器上运行:

#if targetEnvironment(simulator)
    return true
#else
    return false
#endif

(旧的方法仍然有效,但这个新方法更经得起未来的考验)

下面是Objective-C中需要的两个宏。

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 24.0)

用法:

if (IS_IPHONE_X) {
}

我希望它能帮助别人。