Objective-C检测iPhoneX时获取异常尺寸(2001而非2436)
Hey there, I’ve run into this exact issue before! That nativeBounds.size.height = 2001 value you’re seeing isn’t a bug—it’s almost certainly because your app is running in iPad compatibility mode (when you launch an iPhone-only app on an iPad, the system scales it to fit the iPad screen) or you’ve adjusted the simulator window to a non-native resolution.
Let’s break down why relying on nativeBounds for device detection is risky, and share the most reliable methods to detect iPhone X (and all notch-equipped iPhones) correctly:
Why Your Current Method Fails
nativeBounds returns the device’s raw pixel resolution, but this value gets scaled when your app runs in a non-native environment (like iPad compatibility mode). Even in the simulator, dragging the window to a custom size can skew this value—so it’s not a reliable indicator for device type.
Recommended Detection Methods
1. Check Safe Area Insets (Best for Forward Compatibility)
This method works for all iPhone models with a notch (iPhone X and later) without needing to update code for new devices. It leverages the safe area’s top inset, which is significantly larger on notch devices:
- (BOOL)isNotchEquippedDevice { if (@available(iOS 11.0, *)) { // Get the main window (for iOS 13+, use connectedScenes if needed) UIWindow *mainWindow = [UIApplication sharedApplication].windows.firstObject; UIEdgeInsets safeAreaInsets = mainWindow.safeAreaInsets; // Non-notch devices have a top inset of 20pt (status bar height) // Notch devices have a top inset of 44pt return safeAreaInsets.top > 20.0f; } // Pre-iOS 11 devices can't be notch models return NO; }
Note: For iOS 13+, if your app uses scene delegates, you might need to fetch the window from the active scene instead of UIApplication.
2. Detect by Device Model (Precise but Requires Maintenance)
If you need to target specific device models directly, you can fetch the device’s raw model identifier. Just keep in mind you’ll need to update this list as new iPhones are released:
#import <sys/utsname.h> // Helper to get the raw device model - (NSString *)deviceModelIdentifier { struct utsname systemInfo; uname(&systemInfo); return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; } - (BOOL)isIPhoneXOrLater { NSString *model = [self deviceModelIdentifier]; NSArray *notchDeviceModels = @[ @"iPhone10,3", @"iPhone10,6", // iPhone X @"iPhone11,2", // iPhone XS @"iPhone11,4", @"iPhone11,6", // iPhone XS Max @"iPhone11,8", // iPhone XR @"iPhone12,1", @"iPhone12,3", // iPhone 12/12 Pro @"iPhone12,5", @"iPhone12,8", // iPhone 12 Pro Max/iPhone SE (2nd gen) // Add newer models here as they're released ]; return [notchDeviceModels containsObject:model]; }
3. Logical Screen Size Check (Better Than Native Bounds)
If you still prefer using screen dimensions, use the logical resolution (from bounds) instead of raw pixels, and account for screen orientation by checking the maximum dimension:
- (BOOL)isIPhoneXSeriesDevice { CGSize screenSize = [[UIScreen mainScreen] bounds].size; CGFloat maxDimension = MAX(screenSize.width, screenSize.height); // 812pt = iPhone X/XS/11 Pro; 896pt = XS Max/XR/11/12 mini/13 mini etc. return maxDimension == 812.0f || maxDimension == 896.0f; }
This avoids issues with orientation and scaling, since logical points are consistent across native iPhone environments.
Final Takeaway
Avoid using nativeBounds for device detection—it’s too vulnerable to scaling and environment changes. The safe area method is the most future-proof, as it works for all notch devices regardless of their specific screen size.
内容的提问来源于stack exchange,提问作者Eelco

