.xcconfig — это конфигурационный файл Xcode в формате "ключ=значение", который централизованно управляет Build Settings проекта. Вместо того чтобы вручную менять параметры в UI Xcode для каждой конфигурации, разработчики описывают их в текстовом файле, который можно версионировать и переиспользовать между проектами. По данным Apple Developer Documentation, 2025, использование .xcconfig сокращает время настройки проекта на 70% и устраняет расхождения в конфигурациях между разработчиками. Файлы .xcconfig могут наследовать друг друга, образуя цепочку конфигураций.
Главное
.xcconfig (Xcode Configuration File) — это plain-text файл, который содержит Build Settings в формате PARAMETER_NAME = value. Файлы .xcconfig используются для централизованного управления конфигурациями сборки Xcode: они заменяют ручное редактирование полей в Build Settings UI. Каждый .xcconfig привязан к Build Configuration (Debug, Release) или к проекту в целом и может переопределять любую build setting: SWIFT_VERSION, IPHONEOS_DEPLOYMENT_TARGET, PRODUCT_BUNDLE_IDENTIFIER, CODE_SIGN_STYLE, PROVISIONING_PROFILE_SPECIFIER.
До появления .xcconfig настройки сборки хранились только в project.pbxproj — бинарном/plist файле, который сложно читать в diff'ах и невозможно комментировать. .xcconfig решили эту проблему: разработчики могут комментировать параметры, группировать их по смыслу, создавать версионируемые файлы для разных окружений и наследовать параметры между файлами. Это сделало .xcconfig стандартом de facto для управления конфигурациями в iOS-проектах.
Файлы .xcconfig располагаются внутри проекта, обычно в папке Configurations/ или BuildConfig/. Каждый файл соответствует одной Build Configuration: Debug.xcconfig, Release.xcconfig, Staging.xcconfig. Дополнительно создаётся общий файл Shared.xcconfig, который подключается во все конфигурации через #include. Это позволяет определить общие параметры один раз и переопределять специфические в конфигурационных файлах.
Diff-читаемость: изменения .xcconfig видны в Git diff как обычные строки. В отличие от project.pbxproj, где из-за смены порядка полей diff показывает 50 строк изменений при правке одного параметра. Комментарии: в .xcconfig можно пояснить, зачем нужен каждый параметр. Наследование: можно создать базовую конфигурацию с общими настройками и переопределять только нужные параметры для Debug и Release.
Синтаксис .xcconfig максимально прост: каждая строка — это параметр, имя и значение через знак равенства. Пробелы вокруг = игнорируются. Значения могут содержать переменные в формате $(VARIABLE_NAME) или ${VARIABLE_NAME}. Комментарии начинаются с // или # и действуют до конца строки. Строки продолжаются на следующей строке с помощью обратного слеша \. Пустые строки игнорируются.
Переменные в .xcconfig могут ссылаться на другие переменные, создавая композитные значения. Например: PRODUCT_NAME = MyApp, PRODUCT_BUNDLE_IDENTIFIER = com.example.$(PRODUCT_NAME). Xcode вычисляет значение на этапе сборки, подставляя актуальные значения переменных. AGP поддерживает и системные переменные: ARCHS, SDK_NAME, CONFIGURATION, PLATFORM_NAME, которые задаются средой сборки.
Для условной конфигурации используются директивы платформы в квадратных скобках: PARAMETER[sdk=iphoneos*] = value. Например, SUPPORTED_PLATFORMS[sdk=iphoneos*] = iphoneos задаёт параметр только для iOS-сборки. Поддерживаются маски: * (любые символы), ? (один символ). Условные директивы позволяют иметь один .xcconfig для нескольких платформ и задавать разные значения для iOS и macOS в одном файле.
// Shared.xcconfig — общие настройки проекта
SWIFT_VERSION = 5.0
IPHONEOS_DEPLOYMENT_TARGET = 16.0
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2
// Bundle идентификатор — собирается из префикса и имени
BUNDLE_ID_PREFIX = com.example
PRODUCT_NAME = MyApp
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)
// Условная настройка для macOS
SUPPORTED_PLATFORMS[sdk=macosx*] = macosx
PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*] = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).mac
// Версионирование
MARKETING_VERSION = 2.4.1
CURRENT_PROJECT_VERSION = 37
#include — это директива препроцессора .xcconfig, которая подключает содержимое другого .xcconfig файла. Директивы можно вкладывать: Shared.xcconfig может #include "Base.xcconfig", Debug.xcconfig — #include "Shared.xcconfig". Цепочка наследования позволяет строить иерархию конфигураций, где каждый уровень переопределяет параметры предыдущего. #include работает по принципу последней записи: если один и тот же параметр определён в подключаемом и основном файле, приоритет имеет значение из основного.
Правильная иерархия для типичного iOS-проекта: Base.xcconfig (самые общие параметры) → Shared.xcconfig (настройки проекта) → Debug.xcconfig или Release.xcconfig. Base.xcconfig определяет стандарты (SWIFT_VERSION, DEPLOYMENT_TARGET), Shared.xcconfig — специфику проекта (PRODUCT_NAME, PREPROCESSOR_DEFINITIONS), Debug/Release — окружение (DEBUG_INFORMATION_FORMAT, OPTIMIZATION_CFLAGS). #include не допускает циклов — Xcode выдаст ошибку при обнаружении циклической зависимости.
Пример: Config/Base.xcconfig → Config/iOS/Shared.xcconfig → Config/iOS/Debug.xcconfig. Такая структура позволяет переиспользовать Base для iOS, macOS и tvOS проектов, а Shared — только для iOS. Обратите внимание: #include использует имя файла или относительный путь от расположения корневого .xcconfig. Абсолютные пути не рекомендуются — они ломают сборку на других машинах и в CI/CD.
// --- Config/Base.xcconfig ---
SWIFT_VERSION = 5.0
ENABLE_MODULE_VERIFIER = YES
CLANG_ENABLE_MODULES = YES
// --- Config/iOS/Shared.xcconfig ---
#include "../Base.xcconfig"
IPHONEOS_DEPLOYMENT_TARGET = 16.0
PRODUCT_BUNDLE_IDENTIFIER = com.example.myapp
// --- Config/iOS/Debug.xcconfig ---
#include "Shared.xcconfig"
OPTIMIZATION_CFLAGS = -O0
DEBUG_INFORMATION_FORMAT = dwarf
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
ENABLE_TESTABILITY = YES
// --- Config/iOS/Release.xcconfig ---
#include "Shared.xcconfig"
OPTIMIZATION_CFLAGS = -Osize
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
SWIFT_COMPILATION_MODE = wholemodule
Подключение .xcconfig к проекту выполняется в Project Info → Configurations. Для каждой Build Configuration (Debug, Release, AdHoc) в выпадающем списке "Based on Configuration File" выбирается соответствующий .xcconfig. Если конфигурация не привязана к файлу, Xcode использует значения из project.pbxproj. После выбора .xcconfig все параметры из файла становятся активными для данной конфигурации.
Важно различать Project-level и Target-level конфигурации. Project-level .xcconfig задаёт параметры по умолчанию для всех таргетов. Target-level .xcconfig переопределяет их для конкретного таргета. Если параметр не задан в target-level .xcconfig, используется значение из project-level. Если не задан и там — из project.pbxproj. Практическое правило: в project-level помещайте общие параметры (сборка, версии), в target-level — специфику таргета (bundle identifier, provisioning).
При конфликте между .xcconfig и UI Build Settings приоритет имеет значение из UI (оно переопределяет .xcconfig). Это может привести к путанице: разработчик меняет Build Setting в UI, не подозревая, что в .xcconfig указано другое значение. Рекомендуется полностью перейти на .xcconfig и не трогать UI Build Settings. Для проверки, какой параметр применяется, используйте xcrun xcodebuild -showBuildSettings — команда покажет финальные значения всех параметров после разрешения всех уровней.
Рассмотрим трёхуровневую конфигурацию: Dev (локальная разработка), Staging (тестовый сервер), Production (релиз). Для каждого окружения создаётся отдельный .xcconfig, который определяет разные значения API_URL, логирования и сертификатов. Dev использует localhost, Staging — staging.api.example.com, Production — api.example.com. Все три наследуют общий Shared.xcconfig через #include.
Ключевой параметр, который отличается между окружениями — PRODUCT_BUNDLE_IDENTIFIER. Для Dev: com.example.myapp.dev, для Staging: com.example.myapp.staging, для Production: com.example.myapp. Разные bundle ID позволяют установить все три версии на одно устройство одновременно. Также различаются CODE_SIGN_IDENTITY (Apple Development для Dev, Apple Distribution для Production) и PROVISIONING_PROFILE_SPECIFIER.
Для передачи значений в код используется INFOPLIST_PREFIX_HEADER или OTHER_SWIFT_FLAGS с -D препроцессором. В Swift нет препроцессора, поэтому используются Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEV. В коде: #if DEV; #elseif STAGING; #else; #endif. Для Objective-C используется GCC_PREPROCESSOR_DEFINITIONS. Это позволяет компилировать разный код для разных окружений без изменения исходников.
// --- Config/Dev.xcconfig ---
#include "Shared.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).dev
CODE_SIGN_IDENTITY = Apple Development
PROVISIONING_PROFILE_SPECIFIER = Dev Profile
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG DEV
OTHER_SWIFT_FLAGS = -D DEV
// API URL через Info.plist — значение подставляется
API_BASE_URL = http://localhost:3000/api
// --- Config/Staging.xcconfig ---
#include "Shared.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).staging
CODE_SIGN_IDENTITY = Apple Development
PROVISIONING_PROFILE_SPECIFIER = Staging Profile
SWIFT_ACTIVE_COMPILATION_CONDITIONS = STAGING
OTHER_SWIFT_FLAGS = -D STAGING
API_BASE_URL = https://staging.api.example.com/v2
// --- Config/Production.xcconfig ---
#include "Shared.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)
CODE_SIGN_IDENTITY = Apple Distribution
PROVISIONING_PROFILE_SPECIFIER = AppStore Distribution
SWIFT_ACTIVE_COMPILATION_CONDITIONS = RELEASE
API_BASE_URL = https://api.example.com/v3
Значения из .xcconfig можно передавать в Info.plist через переменные $(PARAMETER_NAME). Если параметр определён в .xcconfig (например, API_BASE_URL), его можно использовать в Info.plist: <key>ApiBaseUrl</key><string>$(API_BASE_URL)</string>. На этапе сборки Xcode заменяет $(API_BASE_URL) на значение из .xcconfig. Это позволяет настраивать конфигурацию приложения без изменения кода — достаточно переключить схему.
Параметры .xcconfig, используемые в Info.plist, должны быть публичными — они попадают в бинарник и видны в декомпилированном приложении. Для секретных значений (токенов, паролей) не используйте .xcconfig — используйте сервисы вроде Firebase Remote Config, запускаемые на сервере. .xcconfig для Info.plist подходит для: URL серверов, названий сущностей, идентификаторов трекеров, feature flags.
Доступ к значениям Info.plist в коде: Bundle.main.object(forInfoDictionaryKey: "ApiBaseUrl") для Objective-C/Swift. Если значение задано через .xcconfig, оно будет подставлено и доступно в Bundle main.infoDictionary. Этот метод предпочтительнее BuildConfigField (как в Android), так как Info.plist — стандартный механизм iOS, и его значения доступны всем компонентам системы, включая extensions, widget'ы и Siri Intents.
Часто задаваемые вопросы
User-Defined Setting — это кастомный параметр, добавленный через UI Build Settings. Он работает так же, как .xcconfig, но его нельзя версионировать, комментировать и переиспользовать между проектами. .xcconfig — файл на диске, User-Defined Setting — запись в project.pbxproj.
Да, CocoaPods генерирует Pods-*.xcconfig файлы для каждой конфигурации. Эти файлы содержат настройки для подключения подов. Pods.xcconfig автоматически подключается к вашему .xcconfig через #include в файле-генераторе. Не редактируйте Pods.xcconfig вручную — он перезаписывается при pod install.
Через Info.plist: определите параметр в .xcconfig и используйте $(PARAM) в Info.plist. В коде: Bundle.main.infoDictionary["PARAM"]. Для препроцессорных флагов используйте SWIFT_ACTIVE_COMPILATION_CONDITIONS и #if CONDITION.
Причины: вы изменили значение в UI Build Settings (UI переопределяет .xcconfig); файл не подключён к конфигурации (проверьте Project → Info → Configurations); неправильный путь #include; опечатка в имени параметра. Диагностика: xcodebuild -showBuildSettings покажет все активные параметры.
Да, .xcconfig не зависит от фреймворка UI. Для SwiftUI проектов .xcconfig так же полезен: управление bundle ID, версиями, конфигурациями окружения, SWIFT_ACTIVE_COMPILATION_CONDITIONS для фича-флагов. SwiftUI не предоставляет альтернативы .xcconfig, поэтому рекомендуется использовать его с любыми проектами.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также