Xcode 16 no longer sets ENABLE_PREVIEWS=YES for preview builds

Up until now, it was possible to check in build scripts via the ENABLE_PREVIEWS environment variable whether a build for a SwiftUI preview is being executed.

In addition, it was also possible to conditionally compile code for SwiftUI or exclude it from compilation using this variable.

This no longer works with Xcode 16 and the new SwiftUI Preview compilation!

There is still the option to switch to the old system with the "Use Legacy Previews Execution" setting, but as stated in the release notes, this option will be removed at some point.

Which brings us back to the old problem of not being able to exclude build scripts from preview builds and not being able to prevent certain code from being compiled / add special code for SwiftUI previews.

This is a terrible situation, especially for more complex projects in which precisely the points mentioned are important for the build process.

I seriously hope Apple provides us with another environment variable for SwiftUI preview builds that we can use.

Hi,

Sorry to hear the changes are causing difficulties for you.

New in Xcode 16, Previews now shares build products with normal debug builds. There's no difference anymore. This effort drastically reduces preview time since there’s no need to completely rebuild the entire project. This also resolves bugs when previewing in large package graphs and positions us to maintain fidelity with the normal build-and-run behavior. All debug builds are now “enabled for previews” because there's no distinction. The ENABLE_PREVIEWS build setting is only an indicator about the legacy separate build arena for the old execution mode. The new mode that shares all build products will be used when running on a destination with the latest beta OS. The legacy mode will be used when running on an older OS destination for compatibility.

If you want to vary runtime behavior when previewing, you could check the value of ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS”], which is set when a process is launched under previews.

If you have a unique situation where you hoped to vary your build time behavior based on whether a build was going to be used for previews or not, we would be interested in hearing more details about what you’re trying to do.

If you want to workaround this in the short term, as you've identified, you can toggle back on the legacy execution mode all the time by opening a source file with a preview, then toggling the "Editor > Canvas > Use Legacy Previews Execution" menu item. This setting is per-project and only persists for that particular version of Xcode. This is meant as an escape hatch while we work out any issues in the new mode.

Thank you for your quick response!

If you want to vary runtime behavior when previewing, you could check the value of [...]

Switching off certain behavior at runtime is indeed a critical case for us, as we absolutely must prevent certain things like network requests that are normally executed when the app is started. Otherwise internal data about our developers and their behavior during development could leak to other parties since those network requests will happen each time a developer opens a preview.

However, this is not the primary case I wanted to refer to.

If you have a unique situation [...], we would be interested in hearing more details about what you’re trying to do.

We have a relatively large amount of special code that is exclusively there to ensure that SwiftUI previews work correctly and that the views can be displayed in all relevant states.

This includes the typical mocks of types and services used via dependency injection. Usually, it is undesirable for previews to trigger actual network requests, for example; instead, you want simulated results.

These mocks are currently only built for unit tests and previews, compilation conditionals prevent them from being available for other build configurations.

Another example is special code for view models and methods that can change their otherwise internal (or even private) state. These are therefore methods that should not and must not be used by developers in the app's regular code, as they soften the visibility and accessibility of types and thus violate the integrity of the software architecture.

As a specific example, we have view model methods for previews that allow their internal state to be injected or changed from "outside" (i.e. inside the #Preview macro).

I hope this makes it clear why certain code whose sole purpose is for previews may not be included in any other build. Developers should not be able to use this code outside of the context of a SwiftUI preview.

That's also why the dead code stripping build feature is not sufficient for this purpose.

"Editor > Canvas > Use Legacy Previews Execution" solved this for me as well... Interested in a longterm solution though

We are missing ENABLE_PREVIEWS also.

Our use case is: When builds run we also run tools like SwiftGen, SwiftFormat, SwiftLint. This is not wanted while working on SwiftUI previews as it just stretches building times and SwiftFormat can alter your code while editing it. Which is quite annoying.

It's not so much a matter of runtime, more about knowing the build configuration in run scripts during a build.

I'm sorry, but the "we're sorry you're inconvenienced" responses from Apple are not enough.

Either clearly document a full migration path or stop making changes that require an immediate Xcode update.

This is a terrible experience for developers, and the days of Apple torturing engineers into quitting their jobs needs to be over. Do better, think more, Apple.

This has broken the preview process for all Skip customers (see this discussion for a representative complaint). We have been guarding against ENABLE_PREVIEWS when running our tooling from the Xcode build script, and when that broke in Xcode 16 without warning, everyone's SwiftUI previews went bonkers.

Surely there must be some way to prevent running a build script for the preview execution environment? Couldn't there just be a checkbox option to disable running a script when in a preview context? The "Use Legacy Previews Execution" option is not a solution because it will reset on the next Xcode upgrade – again breaking everyone's project without warning.

I compared all the build settings used for normal build and previews build. the only difference I found is target device env.

Here is my temporary solution instead of using ENABLE_PREVIEWS, you have to find your destination id used by Previews (I got this value from "Show environment variables in build log")

if [ "TARGET_DEVICE_IDENTIFIER" = "D09DA454-2EA3-4506-A8DE-2662EB021EA2"]; then exit 0 fi

Xcode 16 no longer sets ENABLE_PREVIEWS=YES for preview builds
 
 
Q