Aplikasi iOS saya menggunakan ketinggian khusus untuk UINavigationBar
yang menyebabkan beberapa masalah pada iPhone X baru.
Apakah seseorang sudah tahu cara mendeteksi secara program (dalam Objective-C) andal jika aplikasi berjalan di iPhone X?
EDIT:
Tentu saja memeriksa ukuran layar dimungkinkan, namun, saya ingin tahu apakah ada beberapa metode "membangun" seperti TARGET_OS_IPHONE
mendeteksi iOS ...
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 812)
NSLog(@"iPhone X");
}
EDIT 2:
Saya tidak berpikir, bahwa pertanyaan saya adalah duplikat dari pertanyaan terkait. Tentu saja, ada metode untuk "mengukur" berbagai properti perangkat saat ini dan menggunakan hasil untuk memutuskan perangkat mana yang digunakan. Namun, ini bukan poin sebenarnya dari pertanyaan saya karena saya mencoba untuk menekankan pada edit pertama saya.
Pertanyaan sebenarnya adalah: "Apakah mungkin mendeteksi secara langsung apakah perangkat saat ini adalah iPhone X (mis. Oleh beberapa fitur SDK) atau apakah saya harus menggunakan pengukuran tidak langsung" ?
Dengan jawaban yang diberikan sejauh ini, saya berasumsi bahwa jawabannya adalah "Tidak, tidak ada metode langsung. Pengukuran adalah cara untuk pergi".
sumber
Jawaban:
Berdasarkan pertanyaan Anda, jawabannya adalah tidak. Tidak ada metode langsung. Untuk informasi lebih lanjut, Anda dapat memperoleh informasi di sini:
dan
Tinggi iPhone X adalah 2436 px
Dari Ukuran dan resolusi Layar Perangkat :
Dari Ukuran dan Orientasi Layar Perangkat :
Swift 3 dan yang lebih baru :
Tujuan-C :
Xamarin.iOS :
Berdasarkan pertanyaan Anda sebagai berikut:
Atau gunakan
screenSize.height
sebagai float812.0f
not int812
.Untuk informasi lebih lanjut, Anda dapat merujuk halaman berikut dalam Pedoman Antarmuka Manusia iOS:
Cepat :
Deteksi dengan
topNotch
:Tujuan-C :
PEMBARUAN :
Jangan menggunakan
userInterfaceIdiom
properti untuk mengidentifikasi tipe perangkat, seperti yang dijelaskan oleh dokumentasi untuk userInterfaceIdiom :Artinya, properti ini hanya digunakan untuk mengidentifikasi gaya tampilan aplikasi yang berjalan. Namun, aplikasi iPhone (bukan yang universal) dapat diinstal di perangkat iPad melalui App store, dalam hal ini,
userInterfaceIdiom
akan mengembalikanUIUserInterfaceIdiomPhone
juga.Cara yang benar adalah dengan mendapatkan nama mesin melalui
uname
. Periksa hal-hal berikut untuk detail:sumber
userInterfaceIdiom
akan mengembalikanUIUserInterfaceIdiomPhone
juga. Jawaban ini salah.Kemungkinan lain, yang bekerja di iOS 11 dan iOS 12 karena iPhone X adalah satu-satunya dengan takik di bagian atas dan inset 44. Itulah yang saya benar-benar deteksi di sini:
Tujuan-C:
Swift 4:
Dan tentu saja, Anda mungkin perlu memeriksa insets area aman kiri dan kanan jika Anda berada dalam orientasi lanskap.
Sunting: _window adalah UIWindow dari AppDelegate, di mana pemeriksaan ini dilakukan dalam aplikasi didFinishLaunchingWithOptions.
Jawaban diperbarui untuk iOS 12 untuk memeriksa apakah top> 24 daripada top> 0.
Sunting: Di simulator, Anda dapat pergi ke Perangkat Keras, Toggle Status Bar Panggilan. Melakukan hal itu menunjukkan kepada saya bahwa ketinggian bilah status tidak berubah pada iPhone X di iOS 11 atau iPhone XS iOS 12 saat terlibat dalam panggilan. Semua yang berubah adalah ikon waktu, yang mendapat latar belakang hijau, dalam kedua kasus. Ini mudah:
sumber
if _window.safeAreaInsets != UIEdgeInsets.zero
untuk memungkinkan orientasi perangkat apa pun.top
,safeAreaInsets.bottom
akan 34 pada iPhone X dan 0 pada perangkat lainAnda harus melakukan berbagai deteksi iPhone X tergantung pada kebutuhan sebenarnya.
untuk berurusan dengan kedudukan tertinggi (statusbar, navbar), dll.
untuk berurusan dengan indikator home bottom (tabbar), dll.
untuk ukuran latar belakang, fitur layar penuh, dll.
Catatan: akhirnya campur dengan
UIDevice.current.userInterfaceIdiom == .phone
Catatan: metode ini harus memiliki storyboard LaunchScreen atau LaunchImages yang tepat
untuk rasio latar belakang, fitur gulir, dll.
Catatan: metode ini harus memiliki storyboard LaunchScreen atau LaunchImages yang tepat
untuk analitik, statistik, pelacakan, dll.
Dapatkan pengenal mesin dan bandingkan dengan nilai yang didokumentasikan:
Untuk memasukkan simulator sebagai iPhone X yang valid dalam analisis Anda:
Untuk memasukkan iPhone XS, XS Max dan XR, cukup cari model yang dimulai dengan "iPhone11,":
untuk dukungan faceID
sumber
return LAContext().biometryType == .typeFaceID
akan bekerja bahkan jika pengguna telah menolak canEvaluatePolicy, tetapi tidak berhasil bagi saya, masih kembali.none
model == "iPhone10,3" || model == "iPhone10,6"
), dan jikacanUseFaceID
mengembalikan false, maka itu berarti ditolak oleh pengguna.Anda dapat melakukan ini untuk mendeteksi perangkat iPhone X berdasarkan dimensi.
Cepat
Tujuan - C
Tapi ,
Ini bukan cara yang memadai. Bagaimana jika Apple mengumumkan iPhone berikutnya dengan dimensi yang sama dari iPhone X. jadi cara terbaik adalah menggunakan string Hardware untuk mendeteksi perangkat.
Untuk perangkat yang lebih baru, string Perangkat Keras adalah seperti di bawah ini.
iPhone 8 - iPhone10,1 atau iPhone 10,4
iPhone 8 Plus - iPhone10,2 atau iPhone 10,5
iPhone X - iPhone10,3 atau iPhone10,6
sumber
[UIDevice currentDevice]
sebagai gantinya[[UIDevice alloc] init]
Lihat model perangkat / nama mesin , JANGAN menggunakan jumlah titik / piksel dalam kode Anda secara langsung, itu kode sulit dan tidak berarti untuk perangkat keras perangkat, model perangkat adalah satu-satunya pengidentifikasi unik untuk jenis perangkat yang cocok .
Hasil:
Lihat jawaban ini .
Implementasi kode lengkap:
sumber
define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds] .size.height == 812.0)
Catatan: - Hati-hati, hanya berfungsi untuk orientasi potret
sumber
nativeScale
dengan3.0
, bukan?Setelah melihat semua jawaban, inilah yang akhirnya saya lakukan:
Solusi (Swift 4.1 kompatibel)
Menggunakan
Catatan
Pra Swift 4.1 Anda dapat memeriksa apakah aplikasi berjalan pada simulator seperti:
Dari Swift 4.1 dan seterusnya, Anda dapat memeriksa apakah aplikasi berjalan pada simulator menggunakan kondisi platform Target environment :
(metode yang lebih lama masih akan berfungsi, tetapi metode baru ini lebih banyak bukti di masa depan)
sumber
Semua jawaban ini berdasarkan dimensi rentan terhadap perilaku yang salah pada perangkat di masa mendatang. Mereka akan bekerja hari ini, tetapi bagaimana jika ada iPhone tahun depan dengan ukuran yang sama tetapi memiliki kamera, dll. Di bawah kaca sehingga tidak ada "takik?" Jika satu-satunya pilihan adalah memperbarui aplikasi, maka itu adalah solusi yang buruk untuk Anda dan pelanggan Anda.
Anda juga dapat memeriksa string model perangkat keras seperti "iPhone10, 1", tetapi itu bermasalah karena kadang-kadang Apple merilis nomor model yang berbeda untuk operator yang berbeda di seluruh dunia.
Pendekatan yang benar adalah mendesain ulang tata letak teratas, atau menyelesaikan masalah yang Anda hadapi dengan ketinggian bilah navigasi khusus (itulah yang akan saya fokuskan). Tetapi, jika Anda memutuskan untuk tidak melakukan hal-hal tersebut, sadari bahwa apa pun yang Anda lakukan adalah peretasan untuk membuatnya berfungsi hari ini , dan Anda harus memperbaikinya di beberapa titik, mungkin beberapa kali, untuk menjaga peretasan tersebut. kerja.
sumber
SWIFT 4+ Jawab
iPhone X, XR, XS, XSMAX, 11 Pro, 11 Pro Max:
Catatan: Perlu perangkat nyata untuk pengujian
Referensi
sumber
SWIFT 4/5 ekstensi dapat digunakan kembali dengan dukungan iPhone 11
sumber
UIDevice.current.hasHomeButton
Ya itu mungkin. Unduh ekstensi UIDevice-Hardware (atau instal melalui CocoaPod 'UIDevice-Hardware') dan kemudian gunakan:
Perhatikan bahwa ini tidak akan berfungsi di Simulator, hanya di perangkat yang sebenarnya.
sumber
ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"]
dalam Simulator untuk mendapatkan nilai aktual dari Xcode.Menurut respons @saswanb, ini adalah versi Swift 4:
sumber
keyWindow
adalahnil
sampai controller tampilan utama telah disebutviewDidAppear
Saya tahu itu hanya solusi Swift , tetapi bisa membantu seseorang.
Saya miliki
globals.swift
di setiap proyek dan salah satu hal yang selalu saya tambahkan adalahDeviceType
dengan mudah mendeteksi perangkat pengguna:Kemudian untuk menggunakannya:
Jika Anda menggunakan
LaunchImage
dalam proyek Anda, pastikan untuk menambahkan gambar untuk semua perangkat yang didukung (seperti XS Max, XR) karenaUIScreen.main.bounds
tidak akan mengembalikan nilai yang tepat tanpa itu.sumber
if DeviceType.iPhoneX { //do something for iPhone X notch }else{ // don’t do anything about notch }
Semua jawaban yang menggunakan
height
hanya sebagian dari cerita karena satu alasan. Jika Anda akan memeriksa seperti itu ketika orientasi perangkatlandscapeLeft
ataulandscapeRight
cek akan gagal, karenaheight
bertukar denganwidth
.Itu sebabnya solusi saya terlihat seperti ini di Swift 4.0:
sumber
Anda tidak boleh berasumsi bahwa satu-satunya perangkat yang Apple rilis dengan ketinggian UINavigationBar yang berbeda adalah iPhone X. Cobalah untuk menyelesaikan masalah ini menggunakan solusi yang lebih umum. Jika Anda ingin bilah selalu 20px lebih besar dari tinggi standarnya, kode Anda harus menambahkan 20px ke ketinggian bilah, alih-alih mengaturnya menjadi 64px (44px + 20px).
sumber
sumber
Swift 3 + 4:
Contoh:
sumber
sumber
sumber
Biasanya, Programmer membutuhkannya untuk membatasi ke atas atau bawah, sehingga metode ini dapat membantu
Untuk sebelum iPhone X metode ini kembali: 0
Untuk iPhone X: 44 dan 34 sesuai
Kemudian tambahkan saja tambahan ini ke batasan atas atau bawah
sumber
Bagi mereka yang mendapatkan 2001px bukannya 2436px untuk ketinggian batas asli (seperti saya), itu karena Anda membuat aplikasi Anda dengan SDK yang lebih lama, sebelum iOS 11 (Xcode 8 bukannya Xcode 9). Dengan SDK yang lebih lama, iOS akan menampilkan aplikasi "kotak hitam" pada iPhone X alih-alih memperluas layar ujung-ke-ujung, di luar "sensor notch". Ini mengurangi ukuran layar yang mengapa properti itu mengembalikan 2001 bukan 2436.
Solusi paling sederhana adalah dengan hanya memeriksa kedua ukuran jika Anda hanya tertarik pada deteksi perangkat. Saya menggunakan metode ini untuk mendeteksi FaceID sambil membangun dengan Xcode SDK yang lebih tua yang tidak memiliki nilai ENUM yang menentukan jenis biometrik. Dalam situasi ini, deteksi perangkat menggunakan ketinggian layar sepertinya cara terbaik untuk mengetahui apakah perangkat itu memiliki FaceID vs TouchID tanpa harus memperbarui Xcode.
sumber
JANGAN gunakan ukuran piksel layar seperti yang disarankan solusi lain, ini buruk karena dapat menghasilkan hasil positif palsu untuk perangkat di masa mendatang; tidak akan berfungsi jika UIWindow belum dirender (AppDelegate), tidak akan berfungsi di aplikasi lansekap, dan dapat gagal pada simulator jika skala diatur.
Sebagai gantinya, saya telah membuat makro untuk tujuan ini, sangat mudah digunakan dan bergantung pada flag perangkat keras untuk mencegah masalah yang disebutkan di atas.
Sunting: Diperbarui untuk mendukung iPhoneX, iPhone XS, iPhoneXR, iPhoneXS Max
Menggunakan:
Yup, sungguh.
Makro:
Cukup salin tempel ini di mana saja, saya lebih suka bagian paling bawah dari file .h saya setelah
@end
sumber
if (@available(iOS 11.0, *)) { [UIApplication sharedApplication].keyWindow.safeAreaInsets.top }
Saya menguraikan jawaban Anda pada jawaban orang lain dan membuat ekstensi cepat pada UIDevice. Saya suka enum cepat dan "semuanya dalam urutan" & dikabutkan. Saya telah menciptakan solusi yang berfungsi baik di perangkat & simulator.
Keuntungan: - antarmuka yang sederhana, misalnya penggunaan
UIDevice.current.isIPhoneX
-UIDeviceModelType
enum memberi Anda kemampuan untuk dengan mudah memperluas fitur dan konstanta spesifik model yang ingin Anda gunakan di aplikasi Anda, misalnya cornerRadiusKekurangan: - ini adalah solusi model spesifik, bukan resolusi spesifik - mis. Jika Apple akan menghasilkan model lain dengan spesifikasi yang sama, ini tidak akan berfungsi dengan benar dan Anda perlu menambahkan model lain untuk membuat ini bekerja => Anda perlu memperbarui Anda aplikasi.
sumber
Mirror
, itu akan lebih cepat digunakansysctlbyname
seperti yang dilakukan dalam Cloud9999Strife menjawab (dan dalam jawaban saya juga).Saya mengandalkan ketinggian Frame Status Bar untuk mendeteksi apakah itu iPhone X:
Ini untuk aplikasi un portrait. Anda juga dapat memeriksa ukurannya sesuai dengan orientasi perangkat. Selain itu, pada iPhone lainnya, Bilah Status mungkin disembunyikan, sehingga ketinggian bingkai
0
. Di iPhone X, Bilah Status tidak pernah disembunyikan.sumber
controller
dengan ini:- (BOOL)prefersStatusBarHidden { return YES; }
Kemudian tinggi statusBar adalah 0.Saya menggunakan kode Peter Kreinz (karena itu bersih dan melakukan apa yang saya butuhkan) tetapi kemudian saya menyadari itu berfungsi tepat ketika perangkat berada di potret (karena bantalan atas akan di atas, jelas) Jadi saya membuat ekstensi untuk menangani semua orientasi dengan bantalan masing-masing, tanpa menyampaikan pada ukuran layar:
Dan di situs panggilan Anda, Anda hanya:
sumber
Atau, Anda dapat melihat pod ' DeviceKit '. Setelah terinstal, yang perlu Anda lakukan untuk memeriksa perangkat adalah:
sumber
November 2019:
Inilah yang saya gunakan di semua proyek produksi saya. Perhatikan bahwa inti ini cukup panjang.
Bekerja dengan simulator 💯
Penggunaan: biarkan inset: CGFloat = DeviceUtility.isIphoneXType? 50.0: 40.0
sumber
Saya harus menyelesaikan masalah yang sama baru-baru ini. Dan sementara pertanyaan ini dijawab secara pasti ("Tidak"), ini dapat membantu orang lain yang membutuhkan perilaku tata letak khusus iPhone X.
Saya tidak benar-benar tertarik pada apakah perangkat itu iPhone X. Saya tertarik pada apakah perangkat memiliki layar berlekuk.
Anda juga bisa menulis
hasOnScreenHomeIndicator
variabel di sepanjang baris yang sama (meskipun periksa area aman bawah, mungkin?).Di atas menggunakan ekstensi saya aktif
UIView
untuk akses mudah ke insets area aman di iOS 10 dan sebelumnya.sumber
Di Portrait saja saya menggunakan lebar dan tinggi bingkai tampilan untuk memeriksa:
Dimensi layar potret tercantum di sini
sumber
Ada beberapa alasan untuk ingin tahu apa perangkat itu.
Anda dapat memeriksa tinggi dan lebar perangkat. Ini berguna untuk tata letak, tetapi Anda biasanya tidak ingin melakukan itu jika Anda ingin tahu perangkat yang tepat.
Untuk keperluan tata letak, Anda juga dapat menggunakan
UIView.safeAreaInsets
.Jika Anda ingin menampilkan nama perangkat, misalnya, untuk dimasukkan dalam email untuk tujuan diagnostik, setelah mengambil model perangkat menggunakan
sysctl ()
, Anda dapat menggunakan yang setara ini untuk mencari nama:sumber