Moja aplikacja na iOS używa niestandardowej wysokości, UINavigationBar
co prowadzi do problemów w nowym iPhonie X.
Czy ktoś już wie, jak niezawodnie wykryć programowo (w Objective-C), czy aplikacja działa na iPhonie X?
EDYTOWAĆ:
Oczywiście możliwe jest sprawdzenie rozmiaru ekranu, jednak zastanawiam się, czy istnieje jakaś metoda „wbudowana”, taka jak TARGET_OS_IPHONE
wykrywanie iOS ...
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 812)
NSLog(@"iPhone X");
}
EDYCJA 2:
Nie sądzę, że moje pytanie jest duplikatem powiązanego 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 zostanie użyte. Jednak nie o to chodziło w moim pytaniu, które starałem się podkreślić w pierwszej edycji.
Rzeczywiste pytanie brzmi: „Czy można bezpośrednio wykryć, czy bieżącym urządzeniem jest iPhone X (np. Za pomocą funkcji SDK), czy też muszę korzystać z pomiarów pośrednich” ?
Na podstawie udzielonych odpowiedzi zakładam, że odpowiedź brzmi: „Nie, nie ma bezpośrednich metod. Pomiary są właściwą drogą”.
źródło
Odpowiedzi:
Na podstawie twojego pytania odpowiedź brzmi „nie”. Nie ma bezpośrednich metod. Aby uzyskać więcej informacji, możesz uzyskać informacje tutaj:
i
Wysokość iPhone'a X wynosi 2436 pikseli
Z ekranu urządzenia Rozmiary i rozdzielczości :
Od urządzeniu ekranu Rozmiary i orientacje :
Swift 3 i nowszy :
Cel C :
Xamarin.iOS :
W oparciu o następujące pytanie:
Lub użyj
screenSize.height
jako float812.0f
not int812
.Aby uzyskać więcej informacji, zapoznaj się z następującą stroną w Wytycznych dla interfejsu człowieka iOS:
Szybki :
Wykryj za pomocą
topNotch
:Cel C :
AKTUALIZACJA :
Nie używaj tej
userInterfaceIdiom
właściwości do identyfikowania typu urządzenia, ponieważ dokumentacja dla userInterfaceIdiom wyjaśnia:Oznacza to, że ta właściwość służy tylko do identyfikacji stylu widoku uruchomionej aplikacji. Jednak aplikacja iPhone (nie uniwersalna) może zostać zainstalowana na urządzeniu iPad za pośrednictwem App Store, w takim przypadku również ją
userInterfaceIdiom
zwróciUIUserInterfaceIdiomPhone
.Właściwy sposób to uzyskanie nazwy komputera
uname
. Sprawdź następujące szczegóły:źródło
userInterfaceIdiom
zwróciUIUserInterfaceIdiomPhone
. Ta odpowiedź jest zła.Inna możliwość, która działa na iOS 11 i iOS 12, ponieważ iPhone X jest jedynym z wycięciem u góry i wstawką 44. Właśnie to tutaj wykrywam:
Cel C:
Swift 4:
I oczywiście może zajść potrzeba sprawdzenia wstawek lewego i prawego obszaru bezpiecznego, jeśli jesteś w orientacji poziomej.
Edycja: _window to UIWindow AppDelegate, gdzie to sprawdzenie jest wykonywane w aplikacji didFinishLaunchingWithOptions.
Odpowiedź zaktualizowana dla iOS 12, aby sprawdzić, czy top> 24 zamiast top> 0.
Edycja: W symulatorze możesz przejść do Sprzęt, Przełącz pasek stanu podczas połączenia. To pokazuje, że wysokość paska stanu nie zmienia się w telefonie iPhone X w systemie iOS 11 lub iPhone XS iOS 12 po nawiązaniu połączenia. Wszystko, co się zmienia, to ikona czasu, która w obu przypadkach ma zielone tło. Oto przystawka:
źródło
if _window.safeAreaInsets != UIEdgeInsets.zero
aby umożliwić dowolną orientację urządzenia.top
,safeAreaInsets.bottom
będzie 34 na iPhone X i 0 na innych urządzeniachBędziesz wykonywać różne wykrycia iPhone'a X w zależności od faktycznej potrzeby.
do radzenia sobie z najwyższym poziomem (pasek stanu, pasek nawigacyjny) itp.
do radzenia sobie z dolnym wskaźnikiem głównym (pasek narzędzi) itp.
rozmiar tła, funkcje pełnoekranowe itp.
Uwaga: ostatecznie wymieszaj z
UIDevice.current.userInterfaceIdiom == .phone
Uwaga: ta metoda wymaga posiadania scenorysu LaunchScreen lub odpowiedniego LaunchImages
dla współczynnika tła, funkcji przewijania itp.
Uwaga: ta metoda wymaga posiadania scenorysu LaunchScreen lub odpowiedniego LaunchImages
do analiz, statystyk, śledzenia itp.
Uzyskaj identyfikator maszyny i porównaj go z udokumentowanymi wartościami:
Aby dołączyć symulator jako prawidłowego iPhone'a X do analizy:
Aby dołączyć iPhone'a XS, XS Max i XR, po prostu wyszukaj modele zaczynające się od „iPhone11”:
do obsługi faceID
źródło
return LAContext().biometryType == .typeFaceID
że zadziała, nawet jeśli użytkownik odmówił canEvaluatePolicy, ale to nie działa dla mnie, wciąż powraca.none
model == "iPhone10,3" || model == "iPhone10,6"
), a jeślicanUseFaceID
zwróci false, oznacza to, że użytkownik odmówił.Możesz to zrobić, aby wykryć urządzenie iPhone X według wymiaru.
Szybki
Cel C
ale ,
To nie jest wystarczający sposób. Co jeśli Apple ogłosi kolejny iPhone o takim samym wymiarze jak iPhone X. więc najlepszym sposobem jest użycie ciągu sprzętowego do wykrycia urządzenia.
W przypadku nowszych urządzeń Ciąg sprzętu 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
źródło
[UIDevice currentDevice]
zamiast[[UIDevice alloc] init]
Sprawdź model urządzenia / nazwę maszyny , NIE używaj liczby punktów / pikseli bezpośrednio w kodzie, jest to twardy kod i nie ma znaczenia dla sprzętu urządzenia, model urządzenia jest jedynym unikalnym identyfikatorem dla odpowiedniego typu urządzenia .
Wynik:
Zobacz tę odpowiedź .
Pełna implementacja kodu:
źródło
zdefiniuj IS_IPHONE_X (IS_IPHONE i& [[granice ekranu głównego UIScreen]] .size.height == 812.0)
Uwaga: - Uważaj, działa dobrze tylko w przypadku orientacji pionowej
źródło
nativeScale
z3.0
, prawda?Po przeanalizowaniu wszystkich odpowiedzi to właśnie skończyłem:
Rozwiązanie (kompatybilne z Swift 4.1)
Posługiwać się
Uwaga
W wersji wcześniejszej niż Swift 4.1 możesz sprawdzić, czy aplikacja działa na symulatorze w następujący sposób:
Począwszy od wersji Swift 4.1, możesz sprawdzić, czy aplikacja działa na symulatorze, używając warunku platformy środowiska docelowego :
(starsza metoda nadal będzie działać, ale ta nowa metoda jest bardziej przyszłościowa)
źródło
Wszystkie te odpowiedzi oparte na wymiarach są podatne na nieprawidłowe zachowanie na przyszłych urządzeniach. Będą działać dzisiaj, ale co będzie, jeśli w przyszłym roku będzie iPhone o tym samym rozmiarze, ale z aparatem itp. Pod szkłem, więc nie będzie „wycięcia”? Jeśli jedyną opcją jest aktualizacja aplikacji, jest to złe rozwiązanie dla Ciebie i Twoich klientów.
Możesz także sprawdzić ciąg modelu sprzętowego, taki jak „iPhone10,1”, ale jest to problematyczne, ponieważ czasami Apple wydaje różne numery modeli dla różnych operatorów na całym świecie.
Prawidłowe podejście polega na przeprojektowaniu górnego układu lub rozwiązaniu problemów z niestandardową wysokością paska nawigacyjnego (na tym właśnie się skupię). Ale jeśli zdecydujesz się nie robić żadnej z tych rzeczy, zdaj sobie sprawę, że to, co robisz, to hack, aby to zadziałało dzisiaj , i będziesz musiał to poprawić w pewnym momencie, być może wiele razy, aby utrzymać hacki pracujący.
źródło
Odpowiedź SWIFT 4+
iPhone X, XR, XS, XSMAX, 11 Pro, 11 Pro Max:
Uwaga: Potrzebujesz prawdziwego urządzenia do testu
Odniesienie
źródło
Wielokrotnego użytku rozszerzenie SWIFT 4/5 z obsługą iPhone'a 11
źródło
UIDevice.current.hasHomeButton
Tak to mozliwe. Pobierz UIDevice-Hardware (lub zainstaluj przez CocoaPod „UIDevice-Hardware”), a następnie użyj:
Pamiętaj, że to nie będzie działać w Symulatorze, tylko na rzeczywistym urządzeniu.
źródło
ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"]
w Symulatorze, aby uzyskać rzeczywiste wartości z Xcode.Zgodnie z odpowiedzią @ saswanb jest to wersja Swift 4:
źródło
keyWindow
jestnil
aż główny sterownik widok nazwałviewDidAppear
Wiem, że to tylko Szybki rozwiązanie, ale może komuś pomóc.
Mam
globals.swift
w każdym projekcie i jedną z rzeczy, które zawsze dodam, jestDeviceType
łatwe wykrycie urządzenia użytkownika:Następnie, aby go użyć:
Jeśli używasz
LaunchImage
w swoim projekcie, pamiętaj, aby dodać obrazy dla wszystkich obsługiwanych urządzeń (takich jak XS Max, XR), ponieważUIScreen.main.bounds
bez nich nie zwróci właściwej wartości.źródło
if DeviceType.iPhoneX { //do something for iPhone X notch }else{ // don’t do anything about notch }
Wszystkie odpowiedzi, które wykorzystują,
height
są tylko połową historii z jednego powodu. Jeśli zamierzasz to sprawdzić, gdy orientacja urządzenia jest ustawiona,landscapeLeft
lublandscapeRight
sprawdzenie się nie powiedzie, ponieważheight
zmieniono z nawidth
.Właśnie dlatego moje rozwiązanie wygląda tak w Swift 4.0:
źródło
Nie należy zakładać, że jedynym urządzeniem, które Apple wypuści z inną wysokością paska UINavigationBar, będzie iPhone X. Spróbuj rozwiązać ten problem za pomocą bardziej ogólnego rozwiązania. Jeśli chcesz, aby pasek zawsze był o 20 pikseli większy niż domyślna wysokość, kod powinien dodać 20 pikseli do wysokości paska, zamiast ustawiać go na 64px (44px + 20px).
źródło
źródło
Swift 3 + 4:
Przykład:
źródło
źródło
źródło
Zwykle programista potrzebuje go do ograniczenia do góry lub do dołu, więc te metody mogą pomóc
Ponieważ przed iPhone X te metody zwracają: 0
Dla iPhone'a X: odpowiednio 44 i 34
Następnie po prostu dodaj te dodatki do górnych lub dolnych ograniczeń
źródło
Dla tych, którzy otrzymali 2001px zamiast 2436px dla natywnej wysokości granic (jak ja), to dlatego, że zbudowałeś aplikację ze starszym SDK przed iOS 11 (Xcode 8 zamiast Xcode 9). W przypadku starszego zestawu SDK system iOS wyświetli aplikacje w „czarnej skrzynce” na iPhonie X zamiast rozszerzać ekran od krawędzi do krawędzi, wykraczając poza górny „wycięcie czujnika”. Zmniejsza to rozmiar ekranu i dlatego ta właściwość zwraca 2001 zamiast 2436.
Najprostszym rozwiązaniem jest sprawdzenie obu rozmiarów, jeśli interesuje Cię tylko wykrywanie urządzeń. Użyłem tej metody do wykrywania FaceID podczas budowania ze starszym zestawem SDK Xcode, 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 na sprawdzenie, czy urządzenie ma FaceID vs TouchID bez konieczności aktualizacji Xcode.
źródło
NIE używaj rozmiaru piksela ekranu, jak sugerują 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 nie został jeszcze zrenderowany (AppDelegate), nie będzie działać w aplikacjach poziomych i może zawieść na symulatorze, jeśli ustawiona jest skala.
Zamiast tego stworzyłem makro do tego celu, jest bardzo łatwy w użyciu i polega na flagach sprzętowych, aby zapobiec wyżej wymienionym problemom.
Edycja: Zaktualizowano w celu obsługi iPhoneX, iPhone XS, iPhoneXR, iPhoneXS Max
Używać:
Tak, naprawdę.
Makro:
Po prostu skopiuj to wklej gdziekolwiek, wolę potem sam dół mojego pliku .h
@end
źródło
if (@available(iOS 11.0, *)) { [UIApplication sharedApplication].keyWindow.safeAreaInsets.top }
Opracowałem na twoich odpowiedziach na inne pytania i zrobiłem szybkie rozszerzenie na UIDevice. Lubię szybkie wyliczenia i „wszystko w porządku” i rozpylone. Stworzyłem rozwiązanie, które działa zarówno na urządzeniu, jak i na symulatorze.
Zalety: - prosty interfejs, użycie np.
UIDevice.current.isIPhoneX
-UIDeviceModelType
enum daje możliwość łatwego rozszerzenia specyficznych dla modelu funkcji i stałych, których chcesz używać w swojej aplikacji, np. CornerRadiusWada: - jest to rozwiązanie specyficzne dla modelu, a nie specyficzne dla rozdzielczości - np. Jeśli Apple wyprodukuje inny model z tymi samymi specyfikacjami, to nie będzie działać poprawnie i musisz dodać inny model, aby to działało => musisz zaktualizować swój app.
źródło
Mirror
, będzie szybciej używać,sysctlbyname
jak zrobiono w odpowiedzi Cloud9999Strife (i również w mojej odpowiedzi).Opieram się na wysokości ramki paska stanu, aby wykryć, czy jest to iPhone X:
To jest dla aplikacji un portret. Możesz również sprawdzić rozmiar zgodnie z orientacją urządzenia. 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.źródło
controller
:- (BOOL)prefersStatusBarHidden { return YES; }
Wówczas wysokość paska statusBar wynosi 0.I był przy użyciu kodu Petera Kreinz użytkownika (ponieważ był czysty i zrobił to, co potrzebne), ale potem zdałem sobie sprawę, że działa tylko wtedy, gdy urządzenie jest włączone portret (od najwyższej wyściółka będzie na wierzchu, oczywiście), więc stworzył rozszerzenie do obsługi wszystkich orientacje z odpowiednimi wypełnieniami, bez przekazywania rozmiaru ekranu:
A w witrynie połączeń po prostu:
źródło
Alternatywnie możesz sprawdzić kapsułkę „ DeviceKit ”. Po zainstalowaniu wszystko, co musisz zrobić, aby sprawdzić urządzenie to:
źródło
Lis 2019:
Oto, czego używam we wszystkich moich projektach produkcyjnych. Zauważ, że ta istota jest dość długa.
Działa z symulatorami 💯
Zastosowanie: niech wstawka: CGFloat = DeviceUtility.isIphoneXType? 50,0: 40,0
źródło
Ostatnio musiałem rozwiązać ten sam problem. I choć odpowiedź na to pytanie jest ostateczna („Nie”), może to pomóc innym, którzy potrzebują określonego układu iPhone'a X.
Naprawdę nie interesowało mnie, czy urządzeniem jest iPhone X. Byłem zainteresowany, czy urządzenie ma ząbkowany wyświetlacz.
Możesz także napisać
hasOnScreenHomeIndicator
zmienną wzdłuż tych samych linii (choć sprawdź dolny bezpieczny obszar, może?).Powyższe używa mojego rozszerzenia
UIView
dla wygodnego dostępu do wstawek do bezpiecznego obszaru na iOS 10 i wcześniejszych.źródło
W Portret tylko używam szerokość widoku Szkielet i wysokość, aby sprawdzić:
Wymiary ekranu pionowego są wymienione tutaj
źródło
Istnieje kilka powodów, dla których warto wiedzieć, jakie jest urządzenie.
Możesz sprawdzić wysokość (i szerokość) urządzenia. Jest to przydatne w przypadku układu, ale zwykle nie chcesz tego robić, jeśli chcesz znać dokładne urządzenie.
Do celów układu możesz także użyć
UIView.safeAreaInsets
.Jeśli chcesz na przykład wyświetlić nazwę urządzenia, 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ć odpowiednika tego do zobrazowania nazwy:źródło