DEV Community

Muhittin Çamdalı
Muhittin Çamdalı

Posted on

UIDesignRequiresCompatibility ends with the iOS 27 SDK: finding the code that paints over Liquid Glass

When iOS 26 introduced Liquid Glass, many teams added one key to Info.plist and moved on: UIDesignRequiresCompatibility, set to YES, keeps the earlier design. Apple's page for the key always called it temporary ("Temporarily use this key while reviewing and refining your app's UI"), and now it has an end date in practice: "The system ignores this key when you build for iOS 27 or later."

The SDK you build with is not entirely your choice. App Store submissions says that starting April 2027, iOS apps uploaded to App Store Connect "must be built with the iOS & iPadOS 27 SDK or later". Today the Upcoming Requirements page still asks for the iOS 26 SDK, so this is a planning item, not an emergency.

Deleting the key is one line. The real work is finding where your own code fights the new bars.

What actually needs review

Apple's Adopting Liquid Glass puts it this way: custom backgrounds and appearances in bars "might overlay or interfere with Liquid Glass". In a typical UIKit app that has been around since iOS 15, that code looks like this (from the test fixture I use below):

let navigation = UINavigationBarAppearance()
navigation.configureWithOpaqueBackground()
navigation.backgroundColor = .harborNavy
navigation.shadowColor = .clear
UINavigationBar.appearance().standardAppearance = navigation
UINavigationBar.appearance().scrollEdgeAppearance = navigation

let tabs = UITabBarAppearance()
tabs.configureWithOpaqueBackground()
tabs.backgroundColor = .white
UITabBar.appearance().isTranslucent = false

UIToolbar.appearance().barTintColor = .harborNavy
Enter fullscreen mode Exit fullscreen mode

None of this is wrong; it is a brand decision made for an older design. With the opt-out ignored, it sits on top of a material the system wants to draw.

Listing it with glassready

I wrote an open-source CLI, glassready, that reads a native iOS, Flutter or React Native/Expo project and lists the opt-out and these places. It does not build, run or change anything. On the native-uikit-optout fixture from its repository:

npx @mcamdali/glassready
Enter fullscreen mode Exit fullscreen mode

Excerpt of today's output (glassready 0.1.3, rules liquid-glass@2026.10.27, exit code 1):

Harbor · native iOS · .
target Harbor: opts out of Liquid Glass (Harbor/Info.plist)

The Liquid Glass opt-out is ignored when built with the iOS 27 SDK; 4 custom styles to review first

ERROR    GLS001 Liquid Glass opt-out that the iOS 27 SDK ignores
         Harbor/Info.plist:42
WARNING  GLS002 Bar appearance with its own background
         Harbor/AppDelegate.swift:28
WARNING  GLS002 Bar appearance with its own background
         Harbor/AppDelegate.swift:38
WARNING  GLS003 Bar colour or translucency set the old way
         Harbor/AppDelegate.swift:42
WARNING  GLS003 Bar colour or translucency set the old way
         Harbor/AppDelegate.swift:44
INFO     GLS006 Blur layer without a Liquid Glass counterpart
         Harbor/PortMapViewController.swift:5
INFO     GLS008 Fixed bar height or safe-area arithmetic
         Harbor/PortMapViewController.swift:26
         A number added to the safe-area insets.

1 error, 4 warnings, 2 info
Enter fullscreen mode Exit fullscreen mode

The last finding is the subtle one. The fixture places a panel 49 points above the bottom safe area, the height of the classic tab bar:

summary.bottomAnchor.constraint(
    equalTo: view.bottomAnchor, constant: -(view.safeAreaInsets.bottom + 49)),
Enter fullscreen mode Exit fullscreen mode

The report's fix: constrain to safeAreaLayoutGuide instead of adding a bar height, do not read the tab bar's frame for layout, and check the screen with the tab bar minimized as well.

The fixes the report gives

Each finding names a fix. For the bars, condensed from the report:

  • Opaque appearances (GLS002): remove configureWithOpaqueBackground() and the background and shadow settings, or apply them only before iOS 26 with if #available(iOS 26.0, *). Move the brand colour to tintColor and the title text attributes.
  • barTintColor, isTranslucent = false (GLS003): remove them, or keep them only for earlier versions; use tintColor for the bar's buttons.
  • Blur layers (GLS006): behind a floating panel, use UIGlassEffect on iOS 26 and later and keep the blur as the fallback; over a photo or a map, keep it.

The repository also has the same app after these fixes. The report on it:

target Harbor: no opt-out (Harbor/Info.plist)

Ready for Liquid Glass: no opt-out and no custom bar styles found
Impact: none (0 of 100)
Already uses: UIGlassEffect

0 errors, 0 warnings, 0 info
Enter fullscreen mode Exit fullscreen mode

React Native, Expo and Flutter

In React Native the opt-out sits in ios/<App>/Info.plist; in Expo it can sit in ios.infoPlist in app.json. On the React Native 0.88.1 fixture (native stack around JavaScript bottom tabs), glassready reports, among others:

WARNING  GLS101 Native stack header with its own background
         App.tsx:54
         headerStyle.backgroundColor paints the header.
INFO     GLS102 Tab bar drawn in JavaScript
         App.tsx:29
         createBottomTabNavigator draws the tab bar in JavaScript.
Enter fullscreen mode Exit fullscreen mode

The rule data explains the second one: a JavaScript tab bar "keeps its look" with the iOS 27 SDK while the native headers and sheets around it become Liquid Glass. For Flutter, the rules flag Cupertino bars that Flutter draws itself and UiKitView platform views next to Flutter widgets.

What the simulator showed

The repository records a simulator comparison from 27 October 2026, which I did not repeat here: the same UIKit app built with Xcode 27.1, with and without the key. On iOS 27.0 the screenshots match, so the key is ignored; on iOS 26.4 they differ. While the key stays, one build shows two designs depending on the device.

Limitations

From the README, and they matter:

  • Patterns, not a compiler. The rules are regular expressions over source text with comments and strings blanked. Generated code, macros or unusual shapes can be missed or matched by mistake.
  • Only the app's own sources. Pods, Swift packages outside the app folder, node_modules and Flutter plugins are not read.
  • .xcconfig files are not read; app.config.js/.ts are read as text, not run.
  • A warning is not a verdict. A brand colour on a bar can be a deliberate decision; the warning says where the code paints over the bar. Look at the screen on an iOS 27 simulator and decide.
  • The impact score sorts projects; in the README's words, "it does not grade the design."

Try it

In your app folder (Node.js 22.12 or later):

npx @mcamdali/glassready
npx @mcamdali/glassready --fail-on error --format markdown --output glassready.md
Enter fullscreen mode Exit fullscreen mode

The second writes a Markdown report for a pull request and fails only on the ignored opt-out (exit 1 on the fixture above).

The opt-out answers how the app will look. Whether it will launch at all with the same SDK is a separate check, covered in "Built with the iOS 27 SDK, a UIKit app without a scene stops at launch".

Repository: github.com/muhittincamdali/glassready (MIT).

Muhittin Camdali is a mobile engineer (iOS, Flutter, React Native) and the author of glassready.

Top comments (0)