Wykryj, czy urządzenie jest iPhone X
Moja aplikacja na iOS używa niestandardowej wysokości dla UINavigationBar
, co prowadzi do pewnych problemów na nowym iPhone X.
Czy ktoś już wie jakniezawodnie wykrywać programowo (w Objective-C) czy aplikacja działa na iPhonie X?
EDIT:
Oczywiście sprawdzanie rozmiaru ekranu jest możliwe, jednak zastanawiam się, czy istnieje jakaś metoda "wbudowana", taka jak TARGET_OS_IPHONE
do wykrywania iOS...
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 812)
NSLog(@"iPhone X");
}
Edytuj 2:
Nie sądzę, że moje pytanie jest duplikatem połączonego pytania. Oczywiście istnieją metody "mierzenia" różnych właściwości bieżącego urządzenia i wykorzystywania wyników do decydowania, które urządzenie jest używane. Jednak nie o to chodziło w moim pytaniu, co starałem się podkreślić w mojej pierwszej edycji.Prawdziwe pytanie brzmi: "czy możliwe jest bezpośrednie wykrycie, czy obecne urządzenie to iPhone X (np. przez jakąś funkcję SDK), Czy muszę używać pomiarów pośrednich"?
Przez odpowiedzi udzielone tak far, zakładam, że odpowiedź brzmi: "Nie, Nie ma bezpośrednich metod. Pomiary są drogą do zrobienia".
30 answers
Na podstawie Twojego pytania, odpowiedź brzmi Nie, Nie ma bezpośrednich metod, aby uzyskać więcej informacji, możesz uzyskać informacje z here 1 i here 2
Jeśli chcesz wykryć iPhone X Wysokość użyj 2436px
Rozmiar i rozdzielczość ekranu urządzenia
Rozmiary i orientacje ekranu urządzenia
Swift 3 i above
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")
case 2688:
print("iPhone Xs Max")
case 1792:
print("iPhone Xr")
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, 2208:
printf("iPhone 6+/6S+/7+/8+");
break;
case 2436:
printf("iPhone X, Xs");
break;
case 2688:
print("iPhone Xs Max")
case 1792:
print("iPhone Xr")
default:
printf("unknown");
}
}
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");
}
//etc...
}
Na podstawie Twojego pytania jak poniżej
Lub użyj screenSize.wysokość jako float 812.0f
nie int 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");
}
Więcej informacji można uzyskać tutaj
Swift
Lub wykryć za pomocą topNotch
var hasTopNotch: Bool {
if #available(iOS 11.0, *) {
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
Objective C
-(BOOL)hasTopNotch{
if (@available(iOS 11.0, *)) {
return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0;
}
return NO;
}
aktualizacja
Nie używaj userInterfaceIdiom
właściwość do identyfikacji typu urządzenia, jak wyjaśnia dokumentacja Apple,
Dla aplikacji uniwersalnych, można użyć tej właściwości, aby dostosować zachowanie aplikacji do określonego typu urządzenia. Na przykład urządzenia iPhone i iPad mają różne rozmiary ekranu, więc możesz tworzyć różne widoki i kontrolki w zależności od typu bieżącego urządzenia.
To znaczy, ta właściwość jest po prostu używana do identyfikacji stylu widoku uruchomionej aplikacji. Jednak aplikacja iPhone (Nie uniwersalna) może być zainstalowana w urządzeniu iPad za pośrednictwem App store, w takim przypadku interfejs użytkownika zwróci również interfejs użytkownika.
Dobrym sposobem jest uzyskanie nazwy Maszyny przez uname
, sprawdź ten wątek dla szczegółów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-05 09:55:31
[1]} kolejna możliwość, która działa na iOS 11 i iOS 12, ponieważ iPhone X jest jedynym z wycięciem na górze i wstawką 44. To właśnie tutaj wykrywam:
BOOL iPhoneX = NO;
if (@available(iOS 11.0, *)) {
UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
if (mainWindow.safeAreaInsets.top > 20.0) {
iPhoneX = YES;
}
}
I oczywiście, jeśli jesteś w orientacji poziomej, może być konieczne sprawdzenie lewej i prawej strefy bezpieczeństwa.
Edit: _window jest UIWindow AppDelegate, gdzie to sprawdzenie odbywa się w aplikacji didFinishLaunchingWithOptions.
Odpowiedź zaktualizowana dla iOS 12 do sprawdzenia jeśli top > 20 zamiast top > 0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 16:19:53
Możesz zrobić tak, aby wykryć iPhone x urządzenie zgodnie z wymiarem.
Swift
if UIDevice().userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436 {
//iPhone X
}
Objective-C
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone && UIScreen.mainScreen.nativeBounds.size.height == 2436) {
//iPhone X
}
Ale ,
To nie jest wystarczający sposób. Co jeśli Apple ogłosiło następny iPhone o tym samym wymiarze iPhone X. najlepszym sposobem jest użycie ciągu sprzętowego do wykrycia urządzenia.Dla nowszych urządzeń ciąg sprzętowy jest jak poniżej.
IPhone 8 - iPhone10, 1 lub iPhone 10,4
IPhone 8 Plus - iPhone10,2 lub iPhone 10,5
IPhone X - iPhone10,3 lub iPhone10,6
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 06:44:36
Wykonasz różne detekcje iPhone ' a X w zależności od rzeczywistej potrzeby.
Do radzenia sobie z najwyższym nacięciem (statusbar, navbar) itp.
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: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
Do obsługi dolnego wskaźnika głównego (tabbara) itp.
class var hasBottomSafeAreaInsets: Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with home indicator: 34.0 on iPhone X, XS, XS Max, XR.
return UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0 > 0
}
return false
}
Dla rozmiaru tła, funkcji pełnoekranowych itp.
class var isIphoneXOrBigger: Bool {
// 812.0 on iPhone X, XS.
// 896.0 on iPhone XS Max, XR.
return UIScreen.main.bounds.height >= 812
}
Uwaga: ewentualnie wymieszać z UIDevice.current.userInterfaceIdiom == .phone
Uwaga: ta metoda wymaga posiadania storyboardu LaunchScreen lub WŁAŚCIWEGO LaunchImages
Dla tła, przewijanie funkcje itp.
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
}
Uwaga: ta metoda wymaga posiadania storyboardu LaunchScreen lub odpowiednich LaunchImages
Do analizy, statystyk, śledzenia itp.
Pobierz identyfikator Maszyny i porównaj go z udokumentowanymi wartościami:
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"
}
Aby włączyć symulator jako poprawny iPhone X do analizy:
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"
}
Aby włączyć iPhone XS, XS Max i XR, po prostu poszukaj modeli zaczynających się od "iPhone11":
return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")
Do obsługi faceID
import LocalAuthentication
/// will fail if user denies canEvaluatePolicy(_:error:)
class var canUseFaceID: Bool {
if #available(iOS 11.0, *) {
return LAContext().biometryType == .typeFaceID
}
return false
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 03:29:37
Sprawdź model urządzenia / nazwę Maszyny , nie używaj bezpośrednio liczby punktów / pikseli w kodzie, to hard code!
#import <sys/utsname.h>
NSString* deviceName()
{
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
}
Wynik:
@"iPhone10,3" on iPhone X (CDMA)
@"iPhone10,6" on iPhone X (GSM)
Zobacz tę odpowiedź .
Pełna implementacja kodu:
#import <sys/utsname.h>
BOOL IsiPhoneX(void)
{
static BOOL isiPhoneX = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#if TARGET_IPHONE_SIMULATOR
NSString *model = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];
#else
struct utsname systemInfo;
uname(&systemInfo);
NSString *model = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
#endif
isiPhoneX = [model isEqualToString:@"iPhone10,3"] || [model isEqualToString:@"iPhone10,6"];
});
return isiPhoneX;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 02:04:15
#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_x (is_iphone && [[uiscreen mainScreen] bounds].rozmiar.wysokość = = 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"]
Uwaga: - uważaj, działa dobrze tylko dla orientacji portretowej
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 14:27:03
Po przyjrzeniu się wszystkim odpowiedziom, tak się skończyło:
Solution (SWIFT 4.1 compatible)
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
}
}
Użyj
if UIDevice.isIphoneX {
// is iPhoneX
} else {
// is not iPhoneX
}
Uwaga
Pre Swift 4.1 możesz sprawdzić, czy aplikacja działa na symulatorze jak tak:
TARGET_OS_SIMULATOR != 0
Od wersji Swift 4.1 i nowszych możesz sprawdzić, czy aplikacja działa na symulatorze, używając Target environment platform condition :
#if targetEnvironment(simulator)
return true
#else
return false
#endif
(starsza metoda nadal będzie działać, ale ta nowa metoda jest bardziej future proof)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 06:54:52
Wszystkie te odpowiedzi oparte na wymiarach są podatne na nieprawidłowe zachowanie na przyszłych urządzeniach. Będą działać dzisiaj, ale co jeśli w przyszłym roku będzie iPhone tego samego rozmiaru, ale ma aparat itp. pod szybą, żeby nie było "nacięć"?"Jeśli jedyną opcją jest aktualizacja aplikacji, jest to słabe rozwiązanie dla Ciebie i Twoich klientów.
Możesz również sprawdzić ciąg modelu sprzętowego typu "iPhone10, 1", ale to problematyczne, ponieważ czasami Apple wypuszcza inny model numery dla różnych przewoźników na całym świecie.
Poprawnym podejściem jest przeprojektowanie górnego układu lub rozwiązanie problemów z niestandardową wysokością paska nawigacyjnego (na tym bym się skupił). Ale jeśli zdecydujesz się nie robić żadnej z tych rzeczy, zdaj sobie sprawę, że cokolwiek robisz, jest hack, aby to zadziałało dzisiaj, i będziesz musiał to poprawić w pewnym momencie, być może wiele razy, aby hacki działały.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 02:29:57
Tak, to możliwe. Pobierz rozszerzenie UIDevice-Hardware (lub zainstaluj przez Cocoapod 'UIDevice-Hardware'), a następnie użyj:
NSString* modelID = [[[UIDevice currentDevice] modelIdentifier];
BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"];
Zauważ, że to nie zadziała w symulatorze, tylko na rzeczywistym urządzeniu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 20:32:05
SWIFT 4 + Odpowiedz
IPhone X, XR, XS, XSMAX:
Uwaga: potrzebujesz prawdziwego urządzenia do testu
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 10:15:50
Według odpowiedzi @saswanb, jest to wersja Swift 4:
var iphoneX = false
if #available(iOS 11.0, *) {
if ((UIApplication.shared.keyWindow?.safeAreaInsets.top)! > CGFloat(0.0)) {
iphoneX = true
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 14:44:09
Wiem, że to tylko szybkie rozwiązanie, ale może komuś pomóc.
Mam globals.swift
w każdym projekcie i jedną z rzeczy, które zawsze dodaję, jest DeviceType
, aby łatwo wykryć urządzenie użytkownika:
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
}
Następnie użyć go:
if DeviceType.iPhoneX {
print("This executes only on iPhoneX")
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-09 09:33:22
Nie powinieneś zakładać, że jedynym urządzeniem, które Apple wyda z inną wysokością UINavigationBar będzie iPhone X. spróbuj rozwiązać ten problem używając bardziej ogólnego rozwiązania. Jeśli chcesz, aby pasek był zawsze o 20px większy niż jego domyślna wysokość, kod powinien dodać 20px do wysokości paska, zamiast ustawiać go na 64px(44px + 20px).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-18 23:57:45
Wszystkie odpowiedzi, które używają height
są tylko połową części historii z jednego powodu. Jeśli masz zamiar sprawdzić w ten sposób, gdy orientacja urządzenia jest landscapeLeft
lub landscapeRight
, sprawdzenie nie powiedzie się, ponieważ height
jest zamienione na width
.
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-27 21:21:28
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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 06:04:33
Swift 3 + 4:
Bez potrzeby podawania wartości piksela wielkości urządzenia
//UIApplication+SafeArea.swift
extension UIApplication {
static var isDeviceWithSafeArea:Bool {
if #available(iOS 11.0, *) {
if let topPadding = shared.keyWindow?.safeAreaInsets.top,
topPadding > 0 {
return true
}
}
return false
}
}
Przykład:
if UIApplication.isDeviceWithSafeArea {
//e.g. change the frame size height of your UITabBar
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 15:36:50
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-13 08:39:34
- (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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 11:52:39
Zwykle programista potrzebuje go do ograniczenia do góry lub do dołu, więc te metody mogą pomóc
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
}
For before iPhone X these methods return: 0
Dla iPhone X: 44 i 34 odpowiednio
Następnie po prostu dodaj te dodatki do górnej lub dolnej krawędzi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-17 12:00:31
Dla tych, którzy otrzymują 2001px zamiast 2436px dla wysokości natywnych granic (jak ja), to dlatego, że zbudowałeś swoją aplikację ze starszym SDK, przed iOS 11 (Xcode 8 zamiast Xcode 9). Dzięki starszemu zestawowi SDK iOS wyświetli aplikacje " czarne pudełka "na iPhone X zamiast rozszerzać ekran od krawędzi do krawędzi, poza górny"wycięcie czujnika". Zmniejsza to rozmiar ekranu, dlatego właściwość zwraca 2001 zamiast 2436.
Najprostszym rozwiązaniem jest sprawdzenie obu rozmiarów, jeśli są zainteresowani tylko wykrywaniem urządzeń. Użyłem tej metody do wykrywania FaceID podczas budowania ze starszym Xcode SDK, który nie ma wartości ENUM określającej Typ biometryczny. W tej sytuacji wykrywanie urządzenia za pomocą wysokości ekranu wydawało się najlepszym sposobem, aby wiedzieć, czy urządzenie miało FaceID vs TouchID bez konieczności aktualizacji Xcode.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 18:31:35
Opracowałem Twoje odpowiedzi na else i zrobiłem szybkie rozszerzenie na UIDevice. Lubię szybkie wyliczenia i "wszystko w porządku" i rozpylanie. Stworzyłem rozwiązanie, które działa zarówno na urządzeniu, jak i symulatorze.
Zalety:
- prosty interfejs, użycie np. UIDevice.current.isIPhoneX
- UIDeviceModelType
enum daje możliwość łatwego rozszerzenia funkcji i stałych specyficznych dla modelu, które chcesz wykorzystać w swojej aplikacji, np.]}
: - jest to rozwiązanie specyficzne dla modelu, nie specyficzne dla rozdzielczości - np. jeśli Apple wyprodukuje kolejny model z tymi samymi specyfikacjami, to nie będzie działać poprawnie i musisz dodać inny model, aby to działało => musisz zaktualizować aplikację.
extension UIDevice {
enum UIDeviceModelType : Equatable {
///iPhoneX
case iPhoneX
///Other models
case other(model: String)
static func type(from model: String) -> UIDeviceModelType {
switch model {
case "iPhone10,3", "iPhone10,6":
return .iPhoneX
default:
return .other(model: model)
}
}
static func ==(lhs: UIDeviceModelType, rhs: UIDeviceModelType) -> Bool {
switch (lhs, rhs) {
case (.iPhoneX, .iPhoneX):
return true
case (.other(let modelOne), .other(let modelTwo)):
return modelOne == modelTwo
default:
return false
}
}
}
var simulatorModel: String? {
guard TARGET_OS_SIMULATOR != 0 else {
return nil
}
return ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"]
}
var hardwareModel: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let model = 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 model
}
var modelType: UIDeviceModelType {
let model = self.simulatorModel ?? self.hardwareModel
return UIDeviceModelType.type(from: model)
}
var isIPhoneX: Bool {
return modelType == .iPhoneX
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-08 13:45:06
[[2]}polegam na wysokości Ramki paska stanu, aby wykryć, czy jest to iPhone X:
if UIApplication.shared.statusBarFrame.height >= CGFloat(44) {
// It is an iPhone X
}
To jest dla aplikacji un portrait. Możesz również sprawdzić rozmiar zgodnie z orientacją urządzenia. Również na innych iPhone ' ach pasek stanu może być ukryty, więc wysokość ramki wynosi 0
. W telefonie iPhone X pasek stanu nigdy nie jest ukryty.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 17:39:35
Używałem kodu Petera Kreinza (ponieważ był czysty i zrobił to, co potrzebowałem) , ale potem zdałem sobie sprawę, że działa tylko wtedy, gdy urządzenie jest na portrecie (ponieważ Top padding będzie na górze, oczywiście) Dlatego stworzyłem rozszerzenie do obsługi wszystkich orientacji z odpowiednimi paddingami, bez przenoszenia na rozmiar ekranu:
extension UIDevice {
var isIphoneX: Bool {
if #available(iOS 11.0, *), isIphone {
if isLandscape {
if let leftPadding = UIApplication.shared.keyWindow?.safeAreaInsets.left, leftPadding > 0 {
return true
}
if let rightPadding = UIApplication.shared.keyWindow?.safeAreaInsets.right, rightPadding > 0 {
return true
}
} else {
if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 0 {
return true
}
if let bottomPadding = UIApplication.shared.keyWindow?.safeAreaInsets.bottom, bottomPadding > 0 {
return true
}
}
}
return false
}
var isLandscape: Bool {
return UIDeviceOrientationIsLandscape(orientation) || UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation)
}
var isPortrait: Bool {
return UIDeviceOrientationIsPortrait(orientation) || UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
}
var isIphone: Bool {
return self.userInterfaceIdiom == .phone
}
var isIpad: Bool {
return self.userInterfaceIdiom == .pad
}
}
A na twojej stronie po prostu:
let res = UIDevice.current.isIphoneX
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 08:32:53
Ostatnio musiałem rozwiązać ten sam problem. I chociaż to pytanie jest definitywnie odpowiedział ("nie"), może to pomóc innym, którzy potrzebują iPhone X konkretnego zachowania układu.
Nie interesowało mnie, czy urządzenie to iPhone X. interesowało mnie, czy urządzenie ma karbowany wyświetlacz.private static var hasNotchedDisplay: Bool {
if let window = UIApplication.shared.keyWindow {
return (window.compatibleSafeAreaInsets.top > 20.0 || window.compatibleSafeAreaInsets.left > 0.0 || window.compatibleSafeAreaInsets.right > 0.0)
}
return false
}
Możesz również napisać zmienną hasOnScreenHomeIndicator
wzdłuż tych samych linii (chociaż sprawdź dolny obszar bezpieczny, może?).
Powyższe używa mojego rozszerzenia na UIView
dla wygodnego dostępu do wstawek obszaru bezpiecznego w systemie iOS 10 i wcześniejszych.
@objc public extension UIView {
@objc public var compatibleSafeAreaInsets: UIEdgeInsets {
if #available(iOS 11.0, *) {
return safeAreaInsets
} else {
return .zero
}
}
@objc public var compatibleSafeAreaLayoutGuide: UILayoutGuide {
if #available(iOS 11.0, *) {
return safeAreaLayoutGuide
} else {
return layoutMarginsGuide
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-01 03:32:11
Alternatywnie możesz sprawdzić pod' DeviceKit'. Po zainstalowaniu, wszystko, co musisz zrobić, aby sprawdzić urządzenie, to:
import DeviceKit
let device = Device()
if device == .iPhoneX {
// place your code here
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-04 16:57:34
Nie używaj rozmiaru piksela ekranu, jak sugerowały inne rozwiązania, jest to złe, ponieważ może powodować fałszywe alarmy dla przyszłych urządzeń; nie będzie działać, jeśli UIWindow jeszcze nie renderował (AppDelegate), nie będzie działać w aplikacjach krajobrazowych i może nie działać na symulatorze, jeśli skala jest ustawiona.
Zamiast tego zrobiłem makro do tego celu, jest bardzo łatwe w użyciu i opiera się na flagach sprzętowych, aby zapobiec wyżej wymienionym problemom.
Edytuj: Zaktualizowano obsługę iPhoneX, iPhone XS, iphonexr, iPhoneXS MaxDo Użycia:
if (IS_DEVICE_IPHONEX) {
//do stuff
}
Tak, naprawdę.
Makro:
Po prostu skopiuj wklej to gdziekolwiek, wolę sam dół mojego .plik h po @end
#import <sys/utsname.h>
#if TARGET_IPHONE_SIMULATOR
#define IS_SIMULATOR YES
#else
#define IS_SIMULATOR NO
#endif
#define IS_DEVICE_IPHONEX (\
(^BOOL (void){\
NSString *__modelIdentifier;\
if (IS_SIMULATOR) {\
__modelIdentifier = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];\
} else {\
struct utsname __systemInfo;\
uname(&__systemInfo);\
__modelIdentifier = [NSString stringWithCString:__systemInfo.machine encoding:NSUTF8StringEncoding];\
}\
NSString *__iPhoneX_GSM_Identifier = @"iPhone10,6";\
NSString *__iPhoneX_CDMA_Identifier = @"iPhone10,3";\
NSString *__iPhoneXR_Identifier = @"iPhone11,8";\
NSString *__iPhoneXS_Identifier = @"iPhone11,2";\
NSString *__iPhoneXSMax_China_Identifier = @"iPhone11,6";\
NSString *__iPhoneXSMax_Other_Identifier = @"iPhone11,4";\
return ([__modelIdentifier isEqualToString:__iPhoneX_GSM_Identifier] || [__modelIdentifier isEqualToString:__iPhoneX_CDMA_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXR_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXS_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_China_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_Other_Identifier]);\
})()\
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-26 20:48:38
Istnieje kilka powodów, dla których warto wiedzieć, czym jest urządzenie.
Możesz sprawdzić wysokość (i szerokość) urządzenia. Jest to przydatne dla układu, ale zazwyczaj nie chcesz tego robić, jeśli chcesz znać dokładne urządzenie.
Do celów układu można również użyć
UIView.safeAreaInsets
.-
Jeśli chcesz wyświetlić nazwę urządzenia, na przykład, która ma być zawarta w wiadomości e-mail w celach diagnostycznych, po pobraniu modelu urządzenia za pomocą
sysctl ()
, możesz użyć odpowiednik tej nazwy:$ curl http://appledevicenames.com/devices/iPhone10,6 iPhone X
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 15:48:31
Na szybką naprawę, podoba mi się to:
let var:CGFloat = (UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436) ? <iPhoneX> : <AllOthers>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 23:09:43
Najlepszym i najłatwiejszym sposobem wykrycia, czy urządzenie jest iPhone X,
Https://github.com/stephanheilner/UIDevice-DisplayName
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)))}
W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone ' a X.]}Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 09:22:46
W tylko portret używam szerokości i wysokości ramki widoku, aby sprawdzić:
override func viewDidLoad() {
super.viewDidLoad()
// iPhone Xr: -414 x 896
// iPhone Xs Max: -414 x 896
// iPhone X, Xs: -375 x 812
if view.frame.width == 414 && view.frame.height == 896 || view.frame.width == 375 && view.frame.height == 812 {
print("iPhone X")
} else {
print("not iPhone X")
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-16 01:01:45