iOS: Detect if the device is iPhone X family (frameless)
Solution 1
You could "fitler" for the top notch, something like:
var hasTopNotch: Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
Solution 2
Swift 5, iOS 14 supported
Thanks to @Tanin and @DominicMDev, since keyWindow was deprecated in iOS 13
and the iPad Pro has non-zero safeAreaInsets
, this works fine for me.
(Already tested on iPhone 8
, iPhone 11 Pro
and iPad Pro (11-inch)(2nd gen)
Simulators)
extension UIDevice {
/// Returns `true` if the device has a notch
var hasNotch: Bool {
guard #available(iOS 11.0, *), let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first else { return false }
if UIDevice.current.orientation.isPortrait {
return window.safeAreaInsets.top >= 44
} else {
return window.safeAreaInsets.left > 0 || window.safeAreaInsets.right > 0
}
}
}
Solution 3
Since keyWindow was deprecated in iOS 13
, based on the solution to find keyWindow
from here, this one works for me
extension UIDevice {
var hasNotch: Bool {
if #available(iOS 11.0, *) {
let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
return keyWindow?.safeAreaInsets.bottom ?? 0 > 0
}
return false
}
}
Solution 4
This is valid for any orientation. No need to worry about iOS version before 11.0 since iPhone X minimum version is 11.0. Source
extension UIDevice {
var hasNotch: Bool {
if #available(iOS 11.0, *) {
return UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0 > 0
}
return false
}
}
Solution 5
I am doing it like this because the iPadPro has non-zero safeAreaInsets.
extension UIDevice {
/// Returns 'true' if the device has a notch
var hasNotch: Bool {
guard #available(iOS 11.0, *), let window = UIApplication.shared.keyWindow else { return false }
let orientation = UIApplication.shared.statusBarOrientation
if orientation.isPortrait {
return window.safeAreaInsets.top >= 44
} else {
return window.safeAreaInsets.left > 0 || window.safeAreaInsets.right > 0
}
}
}
Mark cubn
Updated on June 28, 2022Comments
-
Mark cubn almost 2 years
In my app there is some logic for frameless devices (iPhoneX, Xs Xs max, Xr). Currently it works base on the model of the devices, so, I detect the model by DeviceKit framework.
But I want to extend this logic to future frameless devices. Probably in one year we will have some extra frameless devices. So, how can I detect if device is frameless or not? It should cover all current frameless devices and future one.
We can not rely on faceID, safeAreaInset, screen height or size. So, then what?
-
MarekR almost 5 yearsThat doesn't work for iPad Pro where statusBarHeight is 24pt
-
claude31 over 4 yearskeyWindow is now deprecated.
-
Saafo over 3 years@NikhilMuskur I've tried on iPhone 8 Plus, iPhone 12 Pro and iPad Pro (11-inch) on iOS 14.1, Xcode 12.1 just now and it works well. What's your condition?
-
Nikhil Muskur over 3 yearsEverything works correctly in the simulator but when I run this on a device the
isPortrait
property is always false -
Saafo over 3 years@NikhilMuskur can you give a more precise description about your situation? On what device and how do you specified the
isPortrait
property is always false? -
Nikhil Muskur over 3 yearsWhile debugging I found that
UIDevice.current.orientation.isPortrait
always returned false andwindow.safeAreaInsets.left
was equal to 0. I tested this on iPhone 11. Strangely the condition is working correctly on the simulator -
Saafo over 3 years@NikhilMuskur Well I've tested on my iPhone X and
UIDevice.current.orientation.isPortrait
works well ( return true when portrait )... -
David over 3 yearsCan confirm, not working, for the rootViewController of UIVindow, later on - it works
-
zhisme over 3 yearsit is a good practice to advocate your code, consider adding some description to your answer
-
Haseeb Javed about 3 yearsMarekR -> try ".bottom instead of .top"
-
fishinear about 3 yearsAlso describe how your answer differs from the 8 existing answers.
-
idris yıldız over 2 years
-
Vladimir Amiorkov over 2 yearsThis breaks on iPad 11 inch 3 generation, because that device has a
keyWindow?.safeAreaInsets.bottom == 20
because it does not have a bottom button. The answer from "Saafo" is what I used in the end. -
StackUnderflow almost 2 years"fitler" ??? Did you mean "filter" ?