Get Notched!

It’s not “Notch”, it’s “Sensor Bar.” — Hermione Granger


There will undoubtedly come a time when you need to detect the iPhone X in your iOS app. The quickest way that comes to mind, is attempting to detect the “notch.” I tried this myself and found issues. Hence this little article.

At the moment, we have something called safeAreaInsets available to us in the iOS 11 SDK. On “classic” iPhones with the Home Button, they are internally or more explicitly:

UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

So the solution seems simple right? > 0 ? notch : normal

On “notched” iPhones, the .top inset is equal to the height of the status bar, plus the navigation bar. The .bottom inset is equal to the height of the “home gesture bar.”

There is a big caveat (or notch, if you will) to adopting this API. If your app uses a non-standard UI, as many with branding requirements do, there is no iron-clad way to detect if deviceHasNotch {} or not.

Several maybe solutions have been found and bandied about already. For example, if you do the following:

let isNotched: Bool
if #available(iOS 11, *) {
isNotched = > 0
} else {
isNotched = false

You still get a false positive when it comes to using a completely transparent navigation bar in your app, on iOS 11. If that’s the case, the value is >0, and so, the flag isNotched will return true, even for an iPhone 8 or below.

Furthermore safeAreaInsets don’t work well in XIBs. You’ll need to remove constraints at build time from IB, and set them yourself in code in association with UIViewController layout guides. While you’re there, don’t allow your UI to run under the bottom gesture bar!

A safer way to detect the notch, is to use the above if #available check, only this time comparing the .bottom value to see if > 0. If it is, it has the home gesture bar, and therefore can be treated as “notched.”

However the SDK is always subject to change. May the odds be ever your favour!


P.S: If anyone has other solutions, let me know! 🙏