.xcconfig es un archivo de configuración de Xcode en formato “clave=valor” que gestiona de forma centralizada los Build Settings de un proyecto. En lugar de cambiar manualmente los parámetros en la interfaz de Xcode para cada configuración, los desarrolladores los describen en un archivo de texto que puede versionarse y reutilizarse entre proyectos. Según Apple Developer Documentation, 2025, el uso de .xcconfig reduce el tiempo de configuración del proyecto en un 70% y elimina las discrepancias de configuración entre desarrolladores. Los archivos .xcconfig pueden heredar unos de otros, formando una cadena de configuraciones.
Puntos clave
.xcconfig (Xcode Configuration File) es un archivo de texto plano que contiene Build Settings en formato PARAMETER_NAME = value. Los archivos .xcconfig se utilizan para la gestión centralizada de las configuraciones de compilación de Xcode: reemplazan la edición manual de campos en la interfaz de Build Settings. Cada .xcconfig está vinculado a una Build Configuration (Debug, Release) o al proyecto en su conjunto y puede sobrescribir cualquier build setting: SWIFT_VERSION, IPHONEOS_DEPLOYMENT_TARGET, PRODUCT_BUNDLE_IDENTIFIER, CODE_SIGN_STYLE, PROVISIONING_PROFILE_SPECIFIER.
Antes de la aparición de .xcconfig, los ajustes de compilación se almacenaban únicamente en project.pbxproj, un archivo binario/plist difícil de leer en los diff e imposible de comentar. .xcconfig resolvió este problema: los desarrolladores pueden comentar los parámetros, agruparlos por significado, crear archivos versionables para diferentes entornos y heredar parámetros entre archivos. Esto convirtió a .xcconfig en el estándar de facto para la gestión de configuraciones en proyectos iOS.
Los archivos .xcconfig se ubican dentro del proyecto, normalmente en la carpeta Configurations/ o BuildConfig/. Cada archivo corresponde a una Build Configuration: Debug.xcconfig, Release.xcconfig, Staging.xcconfig. Además, se crea un archivo común Shared.xcconfig, que se incluye en todas las configuraciones mediante #include. Esto permite definir parámetros comunes una vez y sobrescribir los específicos en los archivos de configuración.
Legibilidad en diff: los cambios en .xcconfig se ven en Git diff como líneas normales. A diferencia de project.pbxproj, donde al cambiar el orden de los campos, el diff muestra 50 líneas de cambios por la edición de un solo parámetro. Comentarios: en .xcconfig se puede explicar para qué sirve cada parámetro. Herencia: se puede crear una configuración base con ajustes comunes y sobrescribir solo los parámetros necesarios para Debug y Release.
La sintaxis de .xcconfig es muy sencilla: cada línea es un parámetro, nombre y valor separados por un signo igual. Los espacios alrededor de = se ignoran. Los valores pueden contener variables en formato $(VARIABLE_NAME) o ${VARIABLE_NAME}. Los comentarios comienzan con // o # y se aplican hasta el final de la línea. Las líneas continúan en la siguiente línea mediante una barra invertida \. Las líneas vacías se ignoran.
Las variables en .xcconfig pueden hacer referencia a otras variables, creando valores compuestos. Por ejemplo: PRODUCT_NAME = MyApp, PRODUCT_BUNDLE_IDENTIFIER = com.example.$(PRODUCT_NAME). Xcode evalúa el valor en tiempo de compilación, sustituyendo los valores reales de las variables. AGP también admite variables del sistema: ARCHS, SDK_NAME, CONFIGURATION, PLATFORM_NAME, que son establecidas por el entorno de compilación.
Para la configuración condicional se utilizan directivas de plataforma entre corchetes: PARAMETER[sdk=iphoneos*] = value. Por ejemplo, SUPPORTED_PLATFORMS[sdk=iphoneos*] = iphoneos establece el parámetro solo para compilaciones iOS. Se admiten comodines: * (cualquier carácter), ? (un solo carácter). Las directivas condicionales permiten tener un solo .xcconfig para varias plataformas y establecer diferentes valores para iOS y macOS en un mismo archivo.
// Shared.xcconfig — configuración común del proyecto
SWIFT_VERSION = 5.0
IPHONEOS_DEPLOYMENT_TARGET = 16.0
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2
// Identificador de bundle — se compone a partir del prefijo y el nombre
BUNDLE_ID_PREFIX = com.example
PRODUCT_NAME = MyApp
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)
// Configuración condicional para macOS
SUPPORTED_PLATFORMS[sdk=macosx*] = macosx
PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*] = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).mac
// Versionado
MARKETING_VERSION = 2.4.1
CURRENT_PROJECT_VERSION = 37
#include es una directiva de preprocesador de .xcconfig que incluye el contenido de otro archivo .xcconfig. Las directivas pueden anidarse: Shared.xcconfig puede #include “Base.xcconfig”, Debug.xcconfig puede #include “Shared.xcconfig”. La cadena de herencia permite construir una jerarquía de configuraciones, donde cada nivel sobrescribe los parámetros del anterior. #include funciona según el principio de la última escritura: si el mismo parámetro está definido tanto en el archivo incluido como en el principal, el valor del principal tiene prioridad.
La jerarquía correcta para un proyecto iOS típico: Base.xcconfig (parámetros más comunes) → Shared.xcconfig (configuración del proyecto) → Debug.xcconfig o Release.xcconfig. Base.xcconfig define estándares (SWIFT_VERSION, DEPLOYMENT_TARGET), Shared.xcconfig — aspectos específicos del proyecto (PRODUCT_NAME, PREPROCESSOR_DEFINITIONS), Debug/Release — el entorno (DEBUG_INFORMATION_FORMAT, OPTIMIZATION_CFLAGS). #include no permite ciclos — Xcode mostrará un error si se detecta una dependencia circular.
Ejemplo: Config/Base.xcconfig → Config/iOS/Shared.xcconfig → Config/iOS/Debug.xcconfig. Esta estructura permite reutilizar Base para proyectos iOS, macOS y tvOS, y Shared solo para iOS. Nota: #include utiliza un nombre de archivo o ruta relativa desde la ubicación del .xcconfig raíz. No se recomiendan rutas absolutas — rompen la compilación en otras máquinas y en 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
La conexión de .xcconfig a un proyecto se realiza en Project Info → Configurations. Para cada Build Configuration (Debug, Release, AdHoc), se selecciona el .xcconfig correspondiente en la lista desplegable “Based on Configuration File”. Si una configuración no está vinculada a un archivo, Xcode utiliza los valores de project.pbxproj. Tras seleccionar .xcconfig, todos los parámetros del archivo se activan para esa configuración.
Es importante distinguir entre configuraciones a nivel de proyecto y a nivel de target. Un .xcconfig a nivel de proyecto establece parámetros predeterminados para todos los targets. Un .xcconfig a nivel de target los sobrescribe para un target específico. Si un parámetro no está definido en el .xcconfig a nivel de target, se utiliza el valor del nivel de proyecto. Si tampoco está definido allí, se utiliza el valor de project.pbxproj. Regla práctica: coloque los parámetros comunes (compilación, versiones) a nivel de proyecto, y los específicos del target (identificador de bundle, aprovisionamiento) a nivel de target.
En caso de conflicto entre .xcconfig y los Build Settings de la interfaz, tiene prioridad el valor de la interfaz (sobrescribe .xcconfig). Esto puede causar confusión: un desarrollador cambia un Build Setting en la interfaz sin saber que .xcconfig especifica un valor diferente. Se recomienda migrar completamente a .xcconfig y no tocar los Build Settings de la interfaz. Para comprobar qué parámetro se aplica, use xcrun xcodebuild -showBuildSettings — el comando mostrará los valores finales de todos los parámetros tras resolver todos los niveles.
Considere una configuración de tres niveles: Dev (desarrollo local), Staging (servidor de pruebas), Production (lanzamiento). Se crea un .xcconfig separado para cada entorno, que define diferentes valores de API_URL, registro y certificados. Dev usa localhost, Staging usa staging.api.example.com, Production usa api.example.com. Los tres heredan el Shared.xcconfig común mediante #include.
El parámetro clave que difiere entre entornos es PRODUCT_BUNDLE_IDENTIFIER. Para Dev: com.example.myapp.dev, para Staging: com.example.myapp.staging, para Production: com.example.myapp. Diferentes bundle IDs permiten instalar las tres versiones en un mismo dispositivo simultáneamente. También difieren CODE_SIGN_IDENTITY (Apple Development para Dev, Apple Distribution para Production) y PROVISIONING_PROFILE_SPECIFIER.
Para pasar valores al código se utiliza INFOPLIST_PREFIX_HEADER u OTHER_SWIFT_FLAGS con -D preprocesador. Swift no tiene preprocesador, por lo que se usan Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEV. En código: #if DEV; #elseif STAGING; #else; #endif. Para Objective-C se usa GCC_PREPROCESSOR_DEFINITIONS. Esto permite compilar código diferente para distintos entornos sin modificar los archivos fuente.
// --- 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
// URL de API mediante Info.plist — el valor se sustituye
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
Los valores de .xcconfig se pueden pasar a Info.plist mediante variables $(PARAMETER_NAME). Si un parámetro está definido en .xcconfig (por ejemplo, API_BASE_URL), se puede usar en Info.plist: <key>ApiBaseUrl</key><string>$(API_BASE_URL)</string>. En tiempo de compilación, Xcode sustituye $(API_BASE_URL) por el valor de .xcconfig. Esto permite configurar la aplicación sin cambiar el código — basta con cambiar el esquema.
Los parámetros de .xcconfig utilizados en Info.plist deben ser públicos — terminan en el binario y son visibles en la aplicación descompilada. No use .xcconfig para valores secretos (tokens, contraseñas) — use servicios como Firebase Remote Config, ejecutados en el servidor. .xcconfig para Info.plist es adecuado para: URLs de servidores, nombres de entidades, identificadores de rastreadores, feature flags.
Acceso a los valores de Info.plist en código: Bundle.main.object(forInfoDictionaryKey: “ApiBaseUrl”) para Objective-C/Swift. Si el valor se establece mediante .xcconfig, se sustituirá y estará disponible en Bundle main.infoDictionary. Este método es preferible a BuildConfigField (como en Android), ya que Info.plist es un mecanismo estándar de iOS y sus valores están disponibles para todos los componentes del sistema, incluyendo extensions, widgets y Siri Intents.
Preguntas frecuentes
User-Defined Setting es un parámetro personalizado añadido a través de los Build Settings de la interfaz. Funciona igual que .xcconfig, pero no se puede versionar, comentar ni reutilizar entre proyectos. .xcconfig es un archivo en disco; User-Defined Setting es una entrada en project.pbxproj.
Sí, CocoaPods genera archivos Pods-*.xcconfig para cada configuración. Estos archivos contienen ajustes para conectar los pods. Pods.xcconfig se enlaza automáticamente a su .xcconfig mediante #include en el archivo generador. No edite Pods.xcconfig manualmente — se sobrescribe durante pod install.
A través de Info.plist: defina un parámetro en .xcconfig y use $(PARAM) en Info.plist. En código: Bundle.main.infoDictionary[“PARAM”]. Para flags de preprocesador, use SWIFT_ACTIVE_COMPILATION_CONDITIONS y #if CONDITION.
Razones: cambió el valor en los Build Settings de la interfaz (la interfaz sobrescribe .xcconfig); el archivo no está vinculado a la configuración (verifique Project → Info → Configurations); ruta de #include incorrecta; error tipográfico en el nombre del parámetro. Diagnóstico: xcodebuild -showBuildSettings mostrará todos los parámetros activos.
Sí, .xcconfig no depende del framework de interfaz. Para proyectos SwiftUI, .xcconfig es igualmente útil: gestión de bundle ID, versiones, configuraciones de entorno, SWIFT_ACTIVE_COMPILATION_CONDITIONS para feature flags. SwiftUI no ofrece una alternativa a .xcconfig, por lo que se recomienda usarlo con cualquier proyecto.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también