Why this happens
When Automatic Reference Counting (ARC) is enabled for an Xcode target, the Clang compiler inserts memory management calls automatically during compilation. Under ARC, the compiler strictly prohibits manual retain-release (MRR) calls such as [obj retain], [obj release], [obj autorelease], or [super dealloc]. If an older Objective-C file or third-party legacy library contains these calls, Clang halts compilation with errors such as 'release' is unavailable: not available in automatic reference counting mode or ARC forbids explicit message send of 'release'.
Most modern projects enable ARC globally across the target via the CLANG_ENABLE_OBJC_ARC setting (labeled in Build Settings as Objective-C Automatic Reference Counting). While converting old source files to modern ARC conventions is the cleanest long-term approach, refactoring large legacy codebases, unit test mocks, or vendored C/Objective-C utilities is not always feasible or safe.
Clang supports granular, file-level overrides. Xcode surfaces this capability through the Compile Sources build phase, allowing you to pass individual compiler flags to Clang for single files or batches of files without altering the target’s overall ARC configuration.
How to fix it
1. Add -fno-objc-arc in Compile Sources
The standard way to disable ARC for a file in an ARC-enabled project is to supply the -fno-objc-arc flag to the Clang compiler for that specific compilation unit.
- In Xcode, open the Project Navigator (
Cmd + 1) and select your top-level project file. - In the project editor, select your app or framework under the Targets list.
- Click the Build Phases tab along the top row.
- Expand the Compile Sources section.
- Scroll or use the search filter in the top-right corner of the Compile Sources box to locate your Objective-C file (e.g.,
LegacyHelper.m). - Double-click the empty space in the Compiler Flags column next to the file name. (Alternatively, select the file row and press
Return). - In the text popover that appears, type:
text
-fno-objc-arc - Press
Returnor click outside the box to confirm. - Clean your build folder using
Shift + Cmd + K, then rebuild withCmd + B.
The compiler will compile that specific file using manual reference counting while retaining ARC for the rest of your target.
2. Apply the flag to multiple files simultaneously
If you are integrating a legacy library with dozens of files, assigning flags one by one is slow. Xcode lets you apply flags to multiple files at once.
- Navigate to Targets > Build Phases > Compile Sources.
- Select the first file you need to modify.
- Hold
Cmdand click each additional file (or holdShiftto select a continuous range of files). - Press
Returnon your keyboard. Xcode opens an editing dialog for the entire selection. - Type
-fno-objc-arcand pressReturn.
Caution: Applying a flag to a multi-file selection replaces any existing compiler flags on those files. If any of those files already had specific warning suppression or macro definition flags, re-enter those flags alongside
-fno-objc-arcseparated by spaces.
3. Enable ARC for a single file in a legacy MRR project
If you maintain an older legacy project where ARC is turned off at the target level (CLANG_ENABLE_OBJC_ARC = NO), you can do the reverse. You can write new Objective-C classes that utilize ARC without converting the entire application.
- Open your target’s Build Phases > Compile Sources.
- Locate your modern Objective-C file (e.g.,
ModernFeature.m). - Double-click the Compiler Flags column for that file.
- Add the ARC activation flag:
text
-fobjc-arc - Press
Returnand rebuild.
This instructs Clang to apply automatic memory management to the designated file while compiling the surrounding target in manual retain-release mode.
4. Isolate legacy code in a separate framework or static library
When dealing with significant blocks of legacy code, scattering compiler flags throughout your main target’s build phases makes long-term maintenance brittle. If a file is deleted and re-added later, Xcode drops the compiler flag and breaks the build.
A cleaner architectural fix is to isolate non-ARC files into their own Cocoa Touch Static Library or Framework target:
- Go to File > New > Target….
- Choose Static Library under the iOS or macOS tab.
- Name the library (e.g.,
LegacyComponents) and add it to your project. - Select the new target, go to Build Settings, and set Objective-C Automatic Reference Counting to No.
- Move all manual reference counting files into this target’s Compile Sources.
- Under your main app target, go to General > Frameworks, Libraries, and Embedded Content and add your new static library.
This keeps your main target’s Compile Sources phase clean and guarantees that any new file added to the legacy module automatically inherits manual retain-release without manual flag management.
How to prevent it
- Migrate legacy Objective-C code: Use modern Objective-C conventions (such as
@property (strong, ...)and removing explicitdeallocimplementations) to allow files to compile under standard ARC. - Verify flags when re-adding files: If you remove a file from your project and later drag it back in, Xcode resets its entry in Compile Sources. Always re-apply
-fno-objc-arcimmediately after re-adding legacy files. - Prefer Swift or modular packages: Encapsulate third-party C or Objective-C dependencies using Swift Package Manager or precompiled binary frameworks rather than compiling raw non-ARC source files directly in your primary application target.
- Use version control audits: Keep an eye on project file changes (
project.pbxproj). If a merge conflict or accidental file re-addition removes thecompilerFlags = "-fno-objc-arc";attribute, builds will fail on CI servers.
FAQ
Can I disable ARC for a Swift file using this flag?
No. ARC is a fundamental, non-optional part of the Swift language and compiler pipeline. The -fno-objc-arc flag is a Clang compiler flag that only applies to Objective-C and Objective-C++ source files (.m and .mm).
Does disabling ARC for a file affect how it interacts with ARC files in the same app?
No. ARC and manual retain-release code interoperate seamlessly within the same runtime. ARC adheres to standard Cocoa memory management naming conventions (such as the method family rules for alloc, init, copy, and new), ensuring that object ownership transfers correctly across boundaries.
What happens if I forget to clean the build folder after adding the flag?
Xcode’s dependency tracker occasionally fails to detect flag changes in the Compile Sources build phase if the source file itself has not been modified. If you see persistent ARC errors immediately after adding -fno-objc-arc, perform a clean build with Shift + Cmd + K to force Clang to recompile the file with the new flag.
Parts of this guide are adapted from content licensed under CC BY-SA 3.0; this article is shared under the same license.
