Мое приложение для iOS использует пользовательскую высоту для UINavigationBar
, что приводит к некоторым проблемам на новом iPhone X .
Кто-то уже знает, как надежно обнаружить программно (в Objective-C), если приложение работает на iPhone X?
EDIT:
Конечно, проверка размера экрана возможна, однако, мне интересно, есть ли какой-нибудь метод «build in», такой как 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) или я должен использовать косвенные измерения "?
По ответам, данным до сих пор, я предполагаю, что ответ «Нет, прямых методов нет. Измерения - это путь ».
На основании вашего вопроса ответ - нет. Прямых методов нет. Для получения дополнительной информации вы можете получить информацию здесь:
а также
Высота iPhone X составляет 2436 пикселей
Из Размеры и разрешения экрана устройства:
Из Размеры и ориентации экрана устройства:
Swift 3 и позже :
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")
}
}
Цель-С :
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, 2208:
printf("iPhone 6+/6S+/7+/8+");
break;
case 2436:
print("iPhone X/XS/11 Pro");
break;
case 2688:
print("iPhone XS Max/11 Pro Max");
break;
case 1792:
print("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
как float 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
:
Если кто-то рассматривает возможность использования надрезов для обнаружения iPhoneX, учтите, что на «ландшафте» то же самое для всех iPhone.
var hasTopNotch: Bool {
if #available(iOS 11.0, *) {
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
Цель-С :
- (BOOL)hasTopNotch {
if (@available(iOS 11.0, *)) {
return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0;
}
return NO;
}
ОБНОВЛЕНИЕ :
Не используйте свойство userInterfaceIdiom
для идентификации типа устройства, как объясняет документация для userInterfaceIdiom:
Для универсальных приложений вы можете использовать это свойство, чтобы адаптировать поведение вашего приложения для определенного типа устройства. Например, устройства iPhone и iPad имеют разные размеры экрана, поэтому вы можете создавать разные виды и элементы управления в зависимости от типа текущего устройства.
То есть это свойство используется только для идентификации стиля просмотра работающего приложения. Однако приложение для iPhone (не универсальное) может быть установлено на устройстве iPad через магазин приложений, в этом случае «userInterfaceIdiom» также вернет «UIUserInterfaceIdiomPhone».
Правильный способ - получить имя машины через uname
. Проверьте следующее для деталей:
Еще одна возможность, которая работает на iOS 11 и iOS 12, потому что iPhone X - единственный с выемкой наверху и вставкой 44. Вот что я действительно обнаруживаю здесь:
Цель-С:
BOOL iPhoneX = NO;
if (@available(iOS 11.0, *)) {
UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
if (mainWindow.safeAreaInsets.top > 24.0) {
iPhoneX = YES;
}
}
Swift 4:
/// Has safe area
///
/// with notch: 44.0 on iPhone X, XS, XS Max, XR.
///
/// without notch: 20.0 on iPhone 8 on iOS 12+.
///
static var hasSafeArea: Bool {
guard #available(iOS 11.0, *), let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 24 else {
return false
}
return true
}
И, конечно, вам может понадобиться проверить вставки левой и правой безопасной зоны, если вы находитесь в ландшафтной ориентации.
Редактировать: _window - это окно UI AppDelegate, где эта проверка выполняется в приложении didFinishLawunchingWithOptions.
Ответ обновлен для iOS 12, чтобы проверить, является ли top > 24, а не top > 0.
Редактировать: В симуляторе вы можете перейти в Hardware, Переключить панель состояния при вызове. Это показывает мне, что высота строки состояния не изменяется на iPhone X на iOS 11 или iPhone XS iOS 12 при участии в вызове. Все, что меняется, - это значок времени, который в обоих случаях получает зеленый фон. Вот оснастка:
Вы должны выполнять различные обнаружения iPhone X в зависимости от реальной необходимости.
class var hasTopNotch: Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 24.0 on iPad Pro 12.9" 3rd generation, 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 24
}
return false
}
class var hasBottomSafeAreaInsets: Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with home indicator: 34.0 on iPhone X, XS, XS Max, XR.
// with home indicator: 20.0 on iPad Pro 12.9" 3rd generation.
return UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0 > 0
}
return false
}
class var isIphoneXOrBigger: Bool {
// 812.0 on iPhone X, XS.
// 896.0 on iPhone XS Max, XR.
return UIScreen.main.bounds.height >= 812
}
Примечание: в конечном итоге смешайте его с UIDevice.current.userInterfaceIdiom == .phone
Примечание: этот метод требует наличия раскадровки LaunchScreen или правильных LaunchImages
class var isIphoneXOrLonger: Bool {
// 812.0 / 375.0 on iPhone X, XS.
// 896.0 / 414.0 on iPhone XS Max, XR.
return UIScreen.main.bounds.height / UIScreen.main.bounds.width >= 896.0 / 414.0
}
Примечание: этот метод требует наличия раскадровки LaunchScreen или правильных LaunchImages
Получить идентификатор машины и сравнить его с документированными значениями:
class var isIphoneX: Bool {
var size = 0
sysctlbyname("hw.machine", nil, &size, nil, 0)
var machine = [CChar](repeating: 0, count: size)
sysctlbyname("hw.machine", &machine, &size, nil, 0)
let model = String(cString: machine)
return model == "iPhone10,3" || model == "iPhone10,6"
}
Включить симулятор в качестве действующего iPhone X в аналитику:
class var isIphoneX: Bool {
let model: String
if TARGET_OS_SIMULATOR != 0 {
model = 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)
model = String(cString: machine)
}
return model == "iPhone10,3" || model == "iPhone10,6"
}
Чтобы включить iPhone XS, XS Max и XR, просто ищите модели, начинающиеся с «iPhone11»:
return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")
import LocalAuthentication
/// will fail if user denies canEvaluatePolicy(_:error:)
class var canUseFaceID: Bool {
if #available(iOS 11.0, *) {
return LAContext().biometryType == .typeFaceID
}
return false
}
Вы можете сделать это, чтобы обнаружить устройство iPhone X в соответствии с размером.
Swift
if UIDevice().userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436 {
//iPhone X
}
Цель - C
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone && UIScreen.mainScreen.nativeBounds.size.height == 2436) {
//iPhone X
}
Но,
Этого недостаточно. Что делать, если Apple анонсирует следующий iPhone с тем же размером iPhone X., так что лучший способ - использовать аппаратную строку для обнаружения устройства.
Для более нового устройства Hardware string выглядит следующим образом.
iPhone 8 - iPhone10,1 или iPhone 10,4
iPhone 8 Plus - iPhone10,2 или iPhone 10,5
iPhone X - iPhone10,3 или iPhone10,6
Проверьте модель устройства / название машины, НЕ используйте количество точек / пикселей в вашем коде напрямую, это [ жесткий код ] ( https ://en.wikipedia.org/wiki/Hard_coding аппаратное обеспечение) и бессмысленно для устройства.
#import <sys/utsname.h>
NSString* deviceName()
{
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
}
Результат:
@"iPhone10,3" on iPhone X (CDMA)
@"iPhone10,6" on iPhone X (GSM)
Обратитесь к этому ответу.
Полная реализация кода:
#import <sys/utsname.h>
NSString * GetDeviceModel(void)
{
static dispatch_once_t onceToken;
static NSString *strModelID = nil;
dispatch_once(&onceToken, ^{
#if TARGET_IPHONE_SIMULATOR
strModelID = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];
#else
struct utsname systemInfo;
uname(&systemInfo);
strModelID = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
#endif
});
return strModelID;
}
// See the `Hardware strings` in https://en.wikipedia.org/wiki/List_of_iOS_devices
BOOL IsiPhoneX(void)
{
NSString *strModelID = GetDeviceModel();
return [strModelID isEqualToString:@"iPhone10,3"] || [strModelID isEqualToString:@"iPhone10,6"];
}
BOOL IsNotchiPhone(void)
{
NSString *strModelID = GetDeviceModel();
return [strModelID isEqualToString:@"iPhone10,3"] || [strModelID isEqualToString:@"iPhone10,6"] || // iPhone X
[strModelID isEqualToString:@"iPhone11,2"] || [strModelID isEqualToString:@"iPhone11,4"] || [strModelID isEqualToString:@"iPhone11,6"] || // iPhone XS (Max)
[strModelID isEqualToString:@"iPhone11,8"] // iPhone XR
[strModelID isEqualToString:@"iPhone12,1"] || [strModelID isEqualToString:@"iPhone12,3"] || [strModelID isEqualToString:@"iPhone12,5"]; // iPhone 11 (Pro (Max))
}
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
#define IS_IPHONE_XS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
#define IS_IPHONE_X_MAX (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 896.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0) // 3.0 for iPhone X, 2.0 for others
#define IS_IPAD_DEVICE [(NSString*)[UIDevice currentDevice].model hasPrefix:@"iPad"]
Примечание: - Будьте осторожны, он отлично работает только для ориентации портрета
Посмотрев на все ответы, я и сделал это
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
}
}
if UIDevice.isIphoneX {
// is iPhoneX
} else {
// is not iPhoneX
}
Pre Swift 4.1 вы можете проверить, работает ли приложение на симуляторе, как это:
TARGET_OS_SIMULATOR != 0
Начиная с Swift 4.1 и далее вы можете проверить, работает ли приложение на симуляторе, используя условие платформы целевой среды:
#if targetEnvironment(simulator)
return true
#else
return false
#endif
(более старый метод все еще будет работать, но этот новый метод является более будущим доказательством)
Все эти ответы, основанные на размерах, подвержены неправильному поведению на будущих устройствах. Они будут работать сегодня, но что, если в следующем году будет iPhone такого же размера, но с камерой и т. Д. под стеклом так что нет "отметки"?«Если единственный вариант - обновить приложение, то это плохое решение для вас и ваших клиентов.
Вы также можете проверить строку аппаратной модели, например «iPhone10,1», но это проблематично, потому что иногда Apple выпускает разные номера моделей для разных операторов по всему миру.
Правильный подход заключается в том, чтобы изменить дизайн верхнего макета или решить проблемы, с которыми вы сталкиваетесь, с высотой пользовательской панели навигации (именно на этом я бы сосредоточился). Но, если вы решите не делать ничего из этого, поймите, что все, что вы делаете, - это хак, чтобы заставить это работать сегодня , и вам нужно будет исправить это в какой-то момент, возможно, несколько раз, чтобы хаки работали.
SWIFT 4+ Ответ
iPhone X, XR, XS, XSMAX:
let deviceType = UIDevice.current.modelName
switch deviceType {
case "iPhone10,3", "iPhone10,6":
print("iPhoneX")
case "iPhone11,2":
print("iPhone XS")
case "iPhone11,4":
print("iPhone XS Max")
case "iPhone11,6":
print("iPhone XS Max China")
case "iPhone11,8":
print("iPhone XR")
default:
break
}
extension UIDevice {
var modelName: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
return identifier
}
}
Да, это возможно. Загрузите расширение UIDevice-Hardware (или установите через CocoaPod 'UIDevice-Hardware'), а затем используйте:
NSString* modelID = [[[UIDevice currentDevice] modelIdentifier];
BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"];
Обратите внимание, что это не будет работать в симуляторе, только на реальном устройстве.
SWIFT 4/5 многоразовое расширение с поддержкой iPhone 11
public extension UIDevice {
public enum `Type` {
case iPad
case iPhone_unknown
case iPhone_5_5S_5C
case iPhone_6_6S_7_8
case iPhone_6_6S_7_8_PLUS
case iPhone_X_Xs
case iPhone_Xs_11_Pro_Max
case iPhone_Xr_11
case iPhone_11_Pro
}
public var hasHomeButton: Bool {
switch type {
case .iPhone_X_Xs, .iPhone_Xr_11, .iPhone_Xs_11_Pro_Max, .iPhone_11_Pro:
return false
default:
return true
}
}
public var type: Type {
if userInterfaceIdiom == .phone {
switch UIScreen.main.nativeBounds.height {
case 1136: return .iPhone_5_5S_5C
case 1334: return .iPhone_6_6S_7_8
case 1920, 2208: return .iPhone_6_6S_7_8_PLUS
case 2436: return .iPhone_X_Xs
case 2688: return .iPhone_Xs_11_Pro_Max
case 1792: return .iPhone_Xr_11
case 2426: return .iPhone_11_Pro
default: return .iPhone_unknown
}
}
return .iPad
}
}
Я знаю, что это только Swift решение, но оно может кому-то помочь.
У меня есть globals.swift
в каждом проекте, и я всегда добавляю одну вещь - DeviceType
, чтобы легко обнаружить устройство пользователя:
struct ScreenSize {
static let width = UIScreen.main.bounds.size.width
static let height = UIScreen.main.bounds.size.height
static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height)
static let maxWH = max(ScreenSize.width, ScreenSize.height)
}
struct DeviceType {
static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH < 568.0
static let iPhone5orSE = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 568.0
static let iPhone678 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 667.0
static let iPhone678p = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 736.0
static let iPhoneX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 812.0
static let iPhoneXRMax = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 896.0
static var hasNotch: Bool {
return iPhoneX || iPhoneXRMax
}
}
Тогда использовать это:
if DeviceType.hasNotch {
print("This executes on all phones with a notch")
}
if DeviceType.iPhone678 {
print("This executes on iPhones 6, 7 and 8")
}
Если вы используете LaunchImage
в своем проекте, обязательно добавьте изображения для всех поддерживаемых устройств (таких как XS Max, XR), потому что UIScreen.main.bounds
не вернет правильное значение без них.
Все ответы, которые используют «высоту», являются лишь половиной части истории по одной причине. Если вы собираетесь проверить, когда ориентация устройства равна landscapeLeft
или landscapeRight
, проверка завершится неудачно, поскольку height
заменяется на width
.
Вот почему мое решение выглядит так в Swift 4.0:
extension UIScreen {
///
static var isPhoneX: Bool {
let screenSize = UIScreen.main.bounds.size
let width = screenSize.width
let height = screenSize.height
return min(width, height) == 375 && max(width, height) == 812
}
}
struct ScreenSize {
static let width = UIScreen.main.bounds.size.width
static let height = UIScreen.main.bounds.size.height
static let maxLength = max(ScreenSize.width, ScreenSize.height)
static let minLength = min(ScreenSize.width, ScreenSize.height)
static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height)
}
struct DeviceType {
static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength < 568.0
static let iPhone5orSE = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 568.0
static let iPhone678 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 667.0
static let iPhone678p = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 736.0
static let iPhoneX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 812.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1024.0
static let IS_IPAD_PRO = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1366.0
}
Не следует предполагать, что единственным устройством, которое Apple выпускает с другой высотой UINavigationBar, будет iPhone X. Попробуйте решить эту проблему, используя более общее решение. Если вы хотите, чтобы планка всегда была на 20 пикселей больше высоты по умолчанию, ваш код должен добавить 20 пикселей к высоте стержня, вместо того, чтобы устанавливать ее на 64px (44px + 20px).
Swift 3 + 4:
без необходимости какого-либо значения пикселя размера устройства
//UIApplication+SafeArea.swift
extension UIApplication {
static var isDeviceWithSafeArea:Bool {
if #available(iOS 11.0, *) {
if let topPadding = shared.keyWindow?.safeAreaInsets.bottom,
topPadding > 0 {
return true
}
}
return false
}
}
Пример:
if UIApplication.isDeviceWithSafeArea {
//e.g. change the frame size height of your UITabBar
}
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)
- (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;
}
}
Обычно программисту это нужно для ограничения сверху или снизу, чтобы эти методы могли помочь
static func extraTop() -> CGFloat {
var top: CGFloat = 0
if #available(iOS 11.0, *) {
if let t = UIApplication.shared.keyWindow?.safeAreaInsets.top {
top = t
}
}
return top
}
static func extraBottom() -> CGFloat {
var bottom: CGFloat = 0
if #available(iOS 11.0, *) {
if let b = UIApplication.shared.keyWindow?.safeAreaInsets.bottom {
bottom = b
}
}
return bottom
}
Для iPhone X эти методы возвращаются: 0
Для iPhone X: 44 и 34 соответственно
Затем просто добавьте эти дополнения к верхним или нижним ограничениям