Мое приложение для 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), или мне нужно использовать косвенные измерения» ?
Исходя из приведенных ответов, я предполагаю, что ответ «Нет, прямых методов нет. Измерения - это путь».
источник
Ответы:
На основании вашего вопроса ответ - нет. Прямых методов нет. Для получения дополнительной информации вы можете получить информацию здесь:
и
Высота iPhone X составляет 2436 пикселей
От устройств Размеры экрана и разрешение :
Из размеров и ориентации экрана устройства :
Свифт 3 и позже :
Цель-C :
Xamarin.iOS :
На основании вашего вопроса следующим образом:
Или используйте
screenSize.height
как float, а812.0f
не int812
.Для получения дополнительной информации вы можете обратиться к следующей странице в Руководстве по интерфейсу пользователя iOS:
Свифт :
Определить с помощью
topNotch
:Цель-C :
ОБНОВЛЕНИЕ :
Не используйте
userInterfaceIdiom
свойство для определения типа устройства, как объясняется в документации для userInterfaceIdiom :То есть это свойство просто используется для определения стиля представления запущенного приложения. Тем не менее, приложение iPhone (не универсальное) может быть установлено на устройстве iPad через App Store, в этом случае
userInterfaceIdiom
будет возвращеноUIUserInterfaceIdiomPhone
.Правильный путь - получить имя машины через
uname
. Проверьте следующее для деталей:источник
userInterfaceIdiom
будет возвращено приложениеUIUserInterfaceIdiomPhone
. Этот ответ неверен.Еще одна возможность, которая работает на iOS 11 и iOS 12, потому что iPhone X является единственным с надписью вверху и вставкой 44. Вот что я действительно обнаруживаю здесь:
Objective-C:
Свифт 4:
И, конечно, вам может понадобиться проверить левые и правые вставки в безопасных зонах, если вы находитесь в альбомной ориентации.
Редактировать: _window является UIWindow AppDelegate, где эта проверка выполняется в приложении didFinishLaunchingWithOptions.
Обновлен ответ для iOS 12, чтобы проверить, является ли top> 24, а не top> 0.
Редактировать: в симуляторе вы можете перейти к Hardware, Toggle In-Call Status Bar. Это показывает, что высота строки состояния не изменяется на iPhone X на iOS 11 или iPhone XS iOS 12 при вызове. Все, что меняется, это значок времени, который в обоих случаях получает зеленый фон. Вот снимок:
источник
if _window.safeAreaInsets != UIEdgeInsets.zero
чтобы учесть любую ориентацию устройства.top
,safeAreaInsets.bottom
будет 34 на iPhone X и 0 на других устройствахВы должны выполнить различные обнаружения iPhone X в зависимости от фактической необходимости.
для работы с высшей меткой (статусбар, навигационная панель) и т. д.
для работы с нижним индикатором дома (вкладка) и т. д.
для размера фона, полноэкранных функций и т. д.
Примечание: в конечном итоге смешайте его с
UIDevice.current.userInterfaceIdiom == .phone
примечанием: этот метод требует наличия раскадровки LaunchScreen или соответствующих LaunchImages
для отношения фона, прокрутки и т. д.
Примечание: этот метод требует наличия раскадровки LaunchScreen или соответствующих LaunchImages
для аналитики, статистики, отслеживания и т. д.
Получите идентификатор машины и сравните его с документированными значениями:
Чтобы включить симулятор в качестве действующего iPhone X в аналитику:
Чтобы включить iPhone XS, XS Max и XR, просто найдите модели, начинающиеся с «iPhone11»:
для поддержки faceID
источник
return LAContext().biometryType == .typeFaceID
это сработает, даже если пользователь отклонит canEvaluatePolicy, но он не работает для меня, он все равно возвращается.none
model == "iPhone10,3" || model == "iPhone10,6"
), и еслиcanUseFaceID
возвращает false, то это означает, что он был отклонен пользователем.Вы можете сделать это, чтобы обнаружить iPhone X устройство соответствии с размером.
стриж
Цель - С
Но ,
Это не достаточный способ. Что делать, если Apple анонсировала следующий iPhone с таким же размером iPhone X. Поэтому лучший способ - использовать аппаратную строку для обнаружения устройства.
Для нового устройства Аппаратная строка указана ниже.
iPhone 8 - iPhone10,1 или iPhone 10,4
iPhone 8 Plus - iPhone10,2 или iPhone 10,5
iPhone X - iPhone10,3 или iPhone10,6
источник
[UIDevice currentDevice]
вместо[[UIDevice alloc] init]
Проверьте модель устройства / имя машины , НЕ используйте количество точек / пикселей в вашем коде напрямую, это жесткий код и не имеет смысла для аппаратного обеспечения устройства, модель устройства является единственным уникальным идентификатором для типа устройства, которое соответствует .
Результат:
Обратитесь к этому ответу .
Полная реализация кода:
источник
определить IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds] .size.height == 812.0)
Примечание: - будьте осторожны, отлично работает только для портретной ориентации
источник
nativeScale
с3.0
, верно?Посмотрев на все ответы, я сделал следующее:
Решение (совместимо с Swift 4.1)
использование
Заметка
В Pre Swift 4.1 вы можете проверить, работает ли приложение на симуляторе, например:
Начиная с Swift 4.1 и далее, вы можете проверить, работает ли приложение на симуляторе с использованием условия платформы среды Target :
(старый метод все еще будет работать, но этот новый метод более перспективен)
источник
Все эти ответы, основанные на размерах, подвержены некорректному поведению на будущих устройствах. Они будут работать сегодня, но что, если в следующем году появится iPhone того же размера, но с камерой и т. Д. Под стеклом, чтобы не было «надреза»? Если единственный вариант - обновить приложение, тогда это плохое решение для вас и ваших клиентов.
Вы также можете проверить строку модели оборудования, такую как «iPhone10,1», но это проблематично, потому что иногда Apple выпускает разные номера моделей для разных операторов по всему миру.
Правильный подход состоит в том, чтобы перепроектировать верхний макет или решить проблемы, возникающие у вас с настраиваемой высотой панели навигации (на этом я бы остановился). Но если вы решите не делать ни одну из этих вещей, осознайте, что все, что вы делаете, является хаком, чтобы заставить это работать сегодня , и вам нужно будет исправить это в какой-то момент, возможно, несколько раз, чтобы сохранить взломы работает.
источник
SWIFT 4+ Ответ
iPhone X, XR, XS, XSMAX, 11 Pro, 11 Pro Max:
Примечание: нужно реальное устройство для теста
Ссылка
источник
Многоразовое расширение SWIFT 4/5 с поддержкой iPhone 11
источник
UIDevice.current.hasHomeButton
Да, это возможно. Загрузите расширение UIDevice-Hardware (или установите через CocoaPod 'UIDevice-Hardware') и затем используйте:
Обратите внимание, что это не будет работать в симуляторе, только на реальном устройстве.
источник
ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"]
в симуляторе, чтобы получить реальные значения из XCode.Согласно ответу @ saswanb, это версия Swift 4:
источник
keyWindow
этоnil
пока главный контроллер представления не назвалviewDidAppear
Я знаю, что это только Свифт решение , но оно может кому-то помочь.
Я имею
globals.swift
в каждом проекте, и одна из вещей, которые я всегда добавляю, состоит в том,DeviceType
чтобы легко обнаружить устройство пользователя:Тогда использовать это:
Если вы используете
LaunchImage
в своем проекте, убедитесь, что добавили изображения для всех поддерживаемых устройств (например, XS Max, XR), потомуUIScreen.main.bounds
что без них не будет возвращено правильное значение.источник
if DeviceType.iPhoneX { //do something for iPhone X notch }else{ // don’t do anything about notch }
Все ответы, которые используют,
height
являются только половиной истории по одной причине. Если вы собираетесь проверить таким образом, когда ориентация устройстваlandscapeLeft
илиlandscapeRight
проверка не удастся, потомуheight
чтоwidth
.Вот почему мое решение выглядит так в Swift 4.0:
источник
Не следует полагать, что единственным устройством, выпущенным Apple с другой высотой UINavigationBar, будет iPhone X. Попробуйте решить эту проблему, используя более общее решение. Если вы хотите, чтобы полоса всегда была на 20px больше высоты по умолчанию, ваш код должен добавить 20px к высоте полосы вместо того, чтобы устанавливать ее на 64px (44px + 20px).
источник
источник
Свифт 3 + 4:
Пример:
источник
источник
источник
Обычно это нужно программисту для ограничения сверху или снизу, поэтому эти методы могут помочь
Для до iPhone X эти методы возвращают: 0
Для iPhone X: 44 и 34 соответственно
Затем просто добавьте эти дополнения к верхним или нижним ограничениям
источник
Для тех, кто получает 2001px вместо 2436px для собственной высоты границ (как я), это потому, что вы создали свое приложение с более старым SDK, до iOS 11 (Xcode 8 вместо Xcode 9). В более старом SDK iOS будет отображать приложения «в черной рамке» на iPhone X вместо того, чтобы расширять экран от края до края, за верхнюю «отметку сенсора». Это уменьшает размер экрана, поэтому это свойство возвращает 2001 вместо 2436.
Самое простое решение - просто проверить оба размера, если вас интересует только обнаружение устройства. Я использовал этот метод для определения FaceID при сборке со старым Xcode SDK, который не имеет значения ENUM, указывающего биометрический тип. В этой ситуации обнаружение устройства с использованием высоты экрана казалось лучшим способом узнать, было ли у устройства FaceID против TouchID без необходимости обновления Xcode.
источник
НЕ используйте размер пикселя экрана, как предлагали другие решения, это плохо, поскольку это может привести к ложным срабатываниям для будущих устройств; не будет работать, если UIWindow еще не визуализировал (AppDelegate), не будет работать в ландшафтных приложениях и может не работать на симуляторе, если установлен масштаб.
Вместо этого я создал макрос для этой цели, он очень прост в использовании и использует аппаратные флаги для предотвращения вышеупомянутых проблем.
Изменить: Обновлено для поддержки iPhoneX, iPhone XS, iPhoneXR, iPhoneXS Max
Использовать:
Да, действительно.
Macro:
Просто скопируйте и вставьте это куда угодно, я предпочитаю самый низ моего .h файла после
@end
источник
if (@available(iOS 11.0, *)) { [UIApplication sharedApplication].keyWindow.safeAreaInsets.top }
Я подробно остановился на ваших ответах и быстро расширил UIDevice. Мне нравятся быстрые перечисления и "все в порядке" и атомизированные. Я создал решение, которое работает как на устройстве, так и на симуляторе.
Преимущества: - простой интерфейс, использование, например,
UIDevice.current.isIPhoneX
-UIDeviceModelType
enum дает вам возможность легко расширять специфические особенности модели и константы, которые вы хотите использовать в своем приложении, например cornerRadius.Недостаток: - это решение для конкретной модели, а не для конкретного разрешения - например, если Apple выпустит другую модель с такими же характеристиками, это не будет работать правильно, и вам нужно добавить другую модель, чтобы это работало => вам необходимо обновить приложение.
источник
Mirror
будет быстрее использовать,sysctlbyname
как в ответе Cloud9999Strife (и в моем ответе тоже).Я полагаюсь на высоту строки состояния строки состояния, чтобы определить, является ли это iPhone X:
Это для приложения и портрета. Вы также можете проверить размер в соответствии с ориентацией устройства. Кроме того, на других iPhone, строка состояния может быть скрыта, поэтому высота кадра
0
. На iPhone X строка состояния никогда не скрывается.источник
controller
с помощью этого:- (BOOL)prefersStatusBarHidden { return YES; }
Тогда высота строки состояния равна 0.Я использовал код Питера Крейнца (потому что он был чистым и делал то, что мне было нужно), но потом я понял, что он работает только тогда, когда устройство находится в портретном режиме (поскольку верхнее заполнение будет сверху), поэтому я создал расширение для обработки всех ориентации с соответствующими отступами, без учета размера экрана:
И на вашем сайте вызова вы просто:
источник
Кроме того, вы можете проверить модуль ' DeviceKit '. После установки все, что вам нужно сделать, чтобы проверить устройство:
источник
Ноябрь 2019 г .:
Вот что я использую во всех своих производственных проектах. Обратите внимание, что этот смысл довольно длинный.
Работает с симуляторами 💯
Использование: let inset: CGFloat = DeviceUtility.isIphoneXType? 50,0: 40,0
источник
Я должен был решить ту же проблему недавно. И хотя на этот вопрос дан окончательный ответ («Нет»), это может помочь тем, кому нужно специфическое поведение макета iPhone X.
Меня не интересовало, было ли это устройство iPhone X. Меня интересовало, имеет ли устройство дисплей с надрезом.
Вы также можете написать
hasOnScreenHomeIndicator
переменную в том же ключе (хотя, возможно, проверьте нижнюю безопасную область?).Выше используется мое расширение
UIView
для удобного доступа к безопасным областям на iOS 10 и более ранних версиях.источник
В Портрете только я использую ширину и высоту фрейма функции представления для проверки:
Размеры портретного экрана приведены здесь
источник
Есть несколько причин, чтобы узнать, что это за устройство.
Вы можете проверить высоту устройства (и ширину). Это полезно для макета, но вы обычно не хотите делать это, если хотите знать точное устройство.
Для макета вы также можете использовать
UIView.safeAreaInsets
.Если вы хотите отобразить имя устройства, например, для включения в электронное письмо для диагностических целей, после получения модели устройства с помощью
sysctl ()
, вы можете использовать эквивалент этого, чтобы вычислить имя:источник