Skip to main content
Written on September 25, 2026, when Xcode 27.0 is the current release and Xcode 27.1 is in beta. The same method applies whenever an app uses APIs from an SDK that is still in beta at the time you need to submit.
iPhone Duo ships with iOS 27.1. Its layout APIs — ArrangementView, GeometryProxy.reservedRegions(kind:) and UIView.reservedRegions(kind:options:) — exist only in the iOS 27.1 SDK, which comes with Xcode 27.1 beta. A project that adopts them hits two restrictions at once:
  • Xcode 27.1 beta builds the project and runs it on the iPhone Duo simulator, but App Store Connect sends a build to review only if it was made with the current public (GM) Xcode or its release candidate. A build from Xcode 27.1 beta uploads, then cannot be added for review.
  • Xcode 27.0 produces builds that App Store Connect accepts for review, but its iOS 27.0 SDK does not declare the iPhone Duo APIs, so the project does not compile.
Wrapping the new code in if #available(iOS 27.1, *) does not fix the Xcode 27.0 build. #available chooses a code path when the app runs; the compiler still has to find every symbol in the SDK it builds against. This guide changes the project so that the same source compiles under both Xcodes. Xcode 27.1 beta compiles the iPhone Duo layout; Xcode 27.0 compiles the layout the app had before, and that build can go to App Store review today. When App Store Connect starts accepting Xcode 27.1 builds for review, you archive the same code with Xcode 27.1 and submit it again. The screenshots follow one app, Memory Lane (the Modaal WikiMemory project), through every step.

Why the usual pre-approval steps fail for this project

The common advice for getting an app approved ahead of a launch date is three steps in App Store Connect: upload a build, submit it for review, and select Manually release this version so the approved version waits until you release it.
Search result listing three steps to pre-approve an App Store release: upload your build, submit for review, choose manual release

The common advice for pre-approving a release. For a build made with Xcode 27.1 beta, step 2 fails.

With a build from Xcode 27.1 beta, the upload in step 1 goes through and step 2 fails: App Store Connect refuses to add the build for review.
App Store Connect error Unable to Add for Review: new apps and app updates must be built with the latest public (GM) versions of Xcode and the SDKs, and apps built with beta versions aren't allowed

App Store Connect, Add for Review, with a build from Xcode 27.1 beta: “This build is using a beta version of Xcode and can’t be submitted.”

The same project built with Xcode 27.0 stops with compile errors, shown in step 4. Steps 1–7 below produce a build from Xcode 27.0 that App Store Connect accepts for review, in which the iPhone Duo code is left out at compile time and kept in the source.

Step 1 — Install Xcode 27.0 and Xcode 27.1 beta side by side

Download both from Apple Developer downloads. Sign in with your Apple Account.
Apple Developer download entry for Xcode 27.1 beta, dated September 18, 2026, 1.89 GB

Xcode 27.1 beta: Swift 6.4 and the iOS 27.1 SDK. It requires macOS Tahoe 26.6 or later on an Apple silicon Mac.

Apple Developer download entry for Xcode 27, dated September 14, 2026, 1.88 GB

Xcode 27, the current release. App Store Connect accepts builds made with it for review.

Expand each .xip and move both apps into /Applications under different names. The prompt in step 5 uses /Applications/Xcode_27_0.app and /Applications/Xcode_27_1_beta.app. If yours are named differently, the agent finds them with ls /Applications | grep -i xcode, which is the first thing the prompt tells it to run. Open each Xcode once and download its iOS platform in Xcode → Settings… → Components. Set up Xcode covers the first launch and the license prompt.
Xcode 27.1 beta Components settings with the iOS 27.1 beta platform highlighted, 15.94 GB

Xcode 27.1 beta, Settings → Components: the iOS 27.1 beta platform is installed.

Xcode 27.0 Components settings with the iOS 27.0 platform highlighted and iOS 27.1 beta 1 Simulator under Other Installed Platforms

Xcode 27.0, Settings → Components: iOS 27.0 is installed. The iOS 27.1 beta simulator that the other Xcode installed is listed under Other Installed Platforms.

Simulator runtimes are shared between Xcode installations on the same Mac, which is why Modaal lists both the iOS 27.0 and iOS 27.1 runtimes under each Xcode in the next step.

Step 2 — Set Xcode 27.1 beta as active in Modaal

Click your profile avatar, choose Set up Xcode, and click Set as active on the installation at /Applications/Xcode_27_1_beta.app. Modaal builds, runs and archives with the active Xcode. Have more than one Xcode installed? explains the switch and the administrator password it asks for.
Modaal Set up Xcode panel with Xcode 27.1 at /Applications/Xcode_27_1_beta.app active and a Set as active button on Xcode 27.0

Xcode 27.1 beta is active: its card is highlighted and has no Set as active button. The panel shows the beta as “Xcode 27.1”; the path identifies which installation is which.


Step 3 — Build and test the iPhone Duo layout

Build the iPhone Duo features with the iOS 27.1 APIs: ArrangementView with its .split and .overlay styles, GeometryProxy.reservedRegions(kind:), and UIView.reservedRegions(kind:options:) in UIKit code. Choose the iPhone Duo simulator in the menu next to the Run button and test the layout there.
Modaal running Memory Lane on the iPhone Duo simulator with a two-pane layout, next to the feature spec for the iPhone Duo split layout

Memory Lane built with Xcode 27.1 beta on the iPhone Duo simulator (iOS 27.1), open: the New Memory pane left of the fold, the feed on the right, the tabs in a rail down the right edge.


Step 4 — Set Xcode 27.0 as active and archive

When you are ready to submit, open Set up Xcode again and click Set as active on Xcode 27.0.
Modaal Set up Xcode panel with Xcode 27.0 at /Applications/Xcode_27_0.app active and a Set as active button on Xcode 27.1

Xcode 27.0 is active. Archive & Upload now builds with the iOS 27.0 SDK.

Open Signing & TestFlight and click Archive & Upload. The first archive fails:
Modaal Upload failed dialog over the archive log, showing compile errors in AdaptiveSplit.swift

Archive & Upload with Xcode 27.0. AdaptiveSplit.swift uses ArrangementView and reservedRegions, which the iOS 27.0 SDK does not declare, so compilation stops and nothing is uploaded.

Building the same project in Xcode 27.0 directly gives the same errors, so the cause is the SDK and not the way Modaal archives:
Xcode build log for target WikiMemoryMain with SDK iOS 27.0, showing 8 errors

The same project built in Xcode 27.0 against SDK iOS 27.0: 8 errors.

The errors are of three kinds:
  • Value of type 'GeometryProxy' has no member 'reservedRegions'
  • Cannot find 'ArrangementView' in scope
  • Cannot infer key path type from context; consider explicitly specifying a root type, on the .map(\.frame) line after each reservedRegions call. It is caused by the first error, and the same fix removes it.
Every error is in code that uses an iOS 27.1 API. The failure dialog’s Fix with agent button sends the build log to the agent. A request to fix the build errors without further instructions can be met by deleting the iPhone Duo code. Use the prompt in step 5 instead: it tells the agent to keep that code and exclude it from the Xcode 27.0 build.

Step 5 — Give the agent the prompt

Paste the prompt below as-is, either into Modaal’s prompt box or into any coding agent session opened at the root of the project’s repository. The prompt names the missing APIs, the SDK versions that tell the two Xcodes apart, the guard to put around each use, and how to verify both builds. Its last section covers Modaal and Duet projects: building with the run_target tool, running scripts/run_tests.sh, and regenerating mocks.
Agent prompt
What the prompt changes explains the guard it adds.

Step 6 — Archive and upload with Xcode 27.0

With Xcode 27.0 still active, run the app on an iOS 27.0 simulator. It shows the layout the app had before iPhone Duo support.
Modaal chat listing four changed files next to Memory Lane running on the iPhone 18 Pro simulator with iOS 27.0

After the agent's change, built with Xcode 27.0 and running on iPhone 18 Pro (iOS 27.0): one pane and the tab bar at the bottom. The agent lists the four files it changed; two of them are generated files whose only change is their fingerprints.

Review the diff and commit it. In a Duet project, include the files under Generated/: without their updated fingerprints, scripts/run_tests.sh and the CI codegen job fail. Then click Archive & Upload again.
Modaal Upload succeeded dialog for Memory Lane 1.0.3 over the archive log

Archive & Upload with Xcode 27.0 succeeds: Memory Lane 1.0.3 (1.0.3.26092521) is in App Store Connect. Processing usually takes 10–30 minutes before the build appears in TestFlight.

In App Store Connect, add the build to a new version and submit it for review. Select Manually release this version if the approved version should wait until you release it.
This build contains only the fallback code path. It shows the layout from before iPhone Duo support on every device, including an iPhone Duo running iOS 27.1. Check that layout on a physical device before you release the build.

Step 7 — Check that Xcode 27.1 beta still builds the iPhone Duo layout

Set Xcode 27.1 beta as active again and run the app on the iPhone Duo simulator. Without any source change, the build compiles the iOS 27.1 code path.
Memory Lane on the iPhone Duo simulator with iOS 27.1, showing the New Memory pane and the feed side by side

The same source built with Xcode 27.1 beta on the iPhone Duo simulator: the two-pane layout from step 3.

The prompt already has the agent check both paths without changing the active Xcode: it builds a second time with DEVELOPER_DIR set to Xcode 27.1 beta and a separate derived-data directory, then uses nm -u on the object files to confirm that only the Xcode 27.1 build references ArrangementView.

What the prompt changes

The guard has to be decided at compile time, and the compiler version cannot decide it: Xcode 27.0 and Xcode 27.1 beta ship the same compiler, Apple Swift 6.4 (swiftlang-6.4.0.34.1), so #if compiler(>=…) and #if swift(>=…) evaluate the same in both. The SDK frameworks differ. Each framework’s .swiftinterface file records a module version, and #if canImport(Module, _version:) compares against it: The agent wraps every use of an iOS 27.1 API in the compile-time guard and keeps the #available check inside it:
#if decides which code is compiled. #available decides which code runs, and is still needed in the Xcode 27.1 build because the deployment target stays the same and devices on older iOS versions take the fallback. The threshold 8.0.85 is the first three parts of the newer SDK’s version rather than the beta’s full build number, so the final Xcode 27.1 release also passes it.

When Xcode 27.1 is released

When Apple releases Xcode 27.1 as a release candidate or final version and App Store Connect accepts builds made with it for review:
  1. Install it and set it as active in Set up Xcode.
  2. Click Archive & Upload. The guard evaluates to true against the iOS 27.1 SDK, so this build contains the iPhone Duo code path.
  3. Submit the build for review as a new version.
None of these steps changes the source. Once you no longer need to build with Xcode 27.0, remove the guards. Every guard uses the same condition text, so one search finds them all:

To install and switch Xcode versions, see Set up Xcode. For how to write prompts like the one in step 5, see Modes and prompts.
Questions about your project? Ask in our community on Discord.
Last modified on September 25, 2026