.xcconfig — co to jest, składnia i zmienne w Xcode

Autor: IT Sectr Opublikowano: 2026-05-30 Czas czytania: 8 min

.xcconfig to plik konfiguracyjny Xcode w formacie „klucz=wartość”, który centralnie zarządza Build Settings projektu. Zamiast ręcznie zmieniać parametry w UI Xcode dla każdej konfiguracji, programiści opisują je w pliku tekstowym, który można wersjonować i wykorzystywać między projektami. Według Apple Developer Documentation, 2025, użycie .xcconfig skraca czas konfiguracji projektu o 70% i eliminuje różnice w konfiguracjach między programistami. Pliki .xcconfig mogą dziedziczyć po sobie, tworząc łańcuch konfiguracji.

Najważniejsze

  • .xcconfig — plik tekstowy z Build Settings w formacie klucz=wartość.
  • Dziedziczenie przez #include pozwala budować łańcuchy konfiguracji (Dev → Staging → Production).
  • Dyrektywy warunkowe platformy (iOS/macOS) i architektury są zarządzane przez konfigurację.
  • Build Settings w .xcconfig nadpisują wartości domyślne w projekcie Xcode.
  • Zarządzanie wersjami — .xcconfig jest przechowywany w Git razem z projektem w xcshareddata.

Co to jest .xcconfig?

.xcconfig (Xcode Configuration File) — to plik tekstowy, który zawiera Build Settings w formacie PARAMETER_NAME = value. Pliki .xcconfig służą do centralnego zarządzania konfiguracjami kompilacji Xcode: zastępują ręczną edycję pól w Build Settings UI. Każdy .xcconfig jest przypisany do Build Configuration (Debug, Release) lub do projektu ogólnie i może nadpisywać dowolne ustawienie: SWIFT_VERSION, IPHONEOS_DEPLOYMENT_TARGET, PRODUCT_BUNDLE_IDENTIFIER, CODE_SIGN_STYLE, PROVISIONING_PROFILE_SPECIFIER.

Przed pojawieniem się .xcconfig ustawienia kompilacji były przechowywane tylko w project.pbxproj — pliku binarnym/plist, który jest trudny do odczytu w diff’ach i nie można go komentować. .xcconfig rozwiązał ten problem: programiści mogą komentować parametry, grupować je według znaczenia, tworzyć pliki z wersjonowaniem dla różnych środowisk i dziedziczyć parametry między plikami. To uczyniło .xcconfig standardem de facto do zarządzania konfiguracjami w projektach iOS.

Pliki .xcconfig znajdują się wewnątrz projektu, zwykle w folderze Configurations/ lub BuildConfig/. Każdy plik odpowiada jednej Build Configuration: Debug.xcconfig, Release.xcconfig, Staging.xcconfig. Dodatkowo tworzony jest wspólny plik Shared.xcconfig, który jest dołączany do wszystkich konfiguracji przez #include. Pozwala to zdefiniować wspólne parametry raz i nadpisywać specyficzne w plikach konfiguracyjnych.

Zalety w porównaniu do UI Build Settings

Czytelność diff’ów: zmiany w .xcconfig są widoczne w Git diff jako zwykłe linie. W przeciwieństwie do project.pbxproj, gdzie z powodu zmiany kolejności pól diff pokazuje 50 linii zmian przy edycji jednego parametru. Komentarze: w .xcconfig można wyjaśnić, do czego służy każdy parametr. Dziedziczenie: można utworzyć bazową konfigurację ze wspólnymi ustawieniami i nadpisywać tylko potrzebne parametry dla Debug i Release.

Składnia i struktura .xcconfig

Zmienne i podstawienia

Składnia .xcconfig jest maksymalnie prosta: każda linia to parametr, nazwa i wartość po znaku równości. Białe znaki wokół = są ignorowane. Wartości mogą zawierać zmienne w formacie $(VARIABLE_NAME) lub ${VARIABLE_NAME}. Komentarze zaczynają się od // lub # i działają do końca linii. Linie są kontynuowane w następnej linii za pomocą odwrotnego ukośnika \. Puste linie są ignorowane.

Zmienne w .xcconfig mogą odwoływać się do innych zmiennych, tworząc wartości złożone. Na przykład: PRODUCT_NAME = MyApp, PRODUCT_BUNDLE_IDENTIFIER = com.example.$(PRODUCT_NAME). Xcode oblicza wartość na etapie kompilacji, podstawiając aktualne wartości zmiennych. Obsługiwane są również zmienne systemowe: ARCHS, SDK_NAME, CONFIGURATION, PLATFORM_NAME, które są ustawiane przez środowisko kompilacji.

Do konfiguracji warunkowej służą dyrektywy platformy w nawiasach kwadratowych: PARAMETER[sdk=iphoneos*] = value. Na przykład SUPPORTED_PLATFORMS[sdk=iphoneos*] = iphoneos ustawia parametr tylko dla kompilacji iOS. Obsługiwane są maski: * (dowolne znaki), ? (jeden znak). Dyrektywy warunkowe pozwalają mieć jeden .xcconfig dla wielu platform i ustawiać różne wartości dla iOS i macOS w jednym pliku.

text
// Shared.xcconfig — ogólne ustawienia projektu
SWIFT_VERSION = 5.0
IPHONEOS_DEPLOYMENT_TARGET = 16.0
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2

// Identyfikator Bundle — składany z prefiksu i nazwy
BUNDLE_ID_PREFIX = com.example
PRODUCT_NAME = MyApp
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)

// Ustawienie warunkowe dla macOS
SUPPORTED_PLATFORMS[sdk=macosx*] = macosx
PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*] = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).mac

// Wersjonowanie
MARKETING_VERSION = 2.4.1
CURRENT_PROJECT_VERSION = 37

Dziedziczenie konfiguracji przez #include

#include — to dyrektywa preprocesora .xcconfig, która dołącza zawartość innego pliku .xcconfig. Dyrektywy można zagnieżdżać: Shared.xcconfig może #include „Base.xcconfig”, Debug.xcconfig — #include „Shared.xcconfig”. Łańcuch dziedziczenia pozwala budować hierarchię konfiguracji, gdzie każdy poziom nadpisuje parametry poprzedniego. #include działa na zasadzie ostatniego zapisu: jeśli ten sam parametr jest zdefiniowany w dołączanym i głównym pliku, priorytet ma wartość z głównego.

Prawidłowa hierarchia dla typowego projektu iOS: Base.xcconfig (najbardziej ogólne parametry) → Shared.xcconfig (ustawienia projektu) → Debug.xcconfig lub Release.xcconfig. Base.xcconfig określa standardy (SWIFT_VERSION, DEPLOYMENT_TARGET), Shared.xcconfig — specyfikę projektu (PRODUCT_NAME, PREPROCESSOR_DEFINITIONS), Debug/Release — środowisko (DEBUG_INFORMATION_FORMAT, OPTIMIZATION_CFLAGS). #include nie dopuszcza cykli — Xcode zgłosi błąd przy wykryciu zależności cyklicznej.

Przykład: Config/Base.xcconfigConfig/iOS/Shared.xcconfigConfig/iOS/Debug.xcconfig. Taka struktura pozwala wykorzystać Base dla projektów iOS, macOS i tvOS, a Shared tylko dla iOS. Uwaga: #include używa nazwy pliku lub ścieżki względnej od lokalizacji głównego .xcconfig. Ścieżki bezwzględne nie są zalecane — powodują błędy kompilacji na innych maszynach i w CI/CD.

text
// --- 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

Podłączanie .xcconfig w projekcie Xcode

Konfiguracje na poziomie projektu i targetu

Podłączenie .xcconfig do projektu wykonuje się w Project Info → Configurations. Dla każdej Build Configuration (Debug, Release, AdHoc) w rozwijanej liście „Based on Configuration File” wybiera się odpowiedni .xcconfig. Jeśli konfiguracja nie jest powiązana z plikiem, Xcode używa wartości z project.pbxproj. Po wybraniu .xcconfig wszystkie parametry z pliku stają się aktywne dla tej konfiguracji.

Ważne jest rozróżnienie konfiguracji na poziomie Project-level i Target-level. .xcconfig na poziomie projektu ustawia domyślne parametry dla wszystkich targetów. .xcconfig na poziomie targetu nadpisuje je dla konkretnego targetu. Jeśli parametr nie jest ustawiony w .xcconfig targetu, używana jest wartość z poziomu projektu. Jeśli nie jest ustawiony i tam — z project.pbxproj. Praktyczna zasada: na poziomie projektu umieszczaj parametry ogólne (kompilacja, wersje), na poziomie targetu — specyfikę targetu (bundle identifier, provisioning).

W przypadku konfliktu między .xcconfig a UI Build Settings priorytet ma wartość z UI (nadpisuje .xcconfig). Może to prowadzić do zamieszania: programista zmienia Build Setting w UI, nie wiedząc, że w .xcconfig określono inną wartość. Zaleca się całkowite przejście na .xcconfig i nie dotykanie UI Build Settings. Aby sprawdzić, który parametr jest stosowany, użyj xcrun xcodebuild -showBuildSettings — polecenie pokaże końcowe wartości wszystkich parametrów po rozwiązaniu wszystkich poziomów.

Przykład: środowiska Dev, Staging, Production

Rozważmy trójpoziomową konfigurację: Dev (lokalny development), Staging (serwer testowy), Production (wydanie). Dla każdego środowiska tworzony jest osobny .xcconfig, który określa różne wartości API_URL, logowania i certyfikatów. Dev używa localhost, Staging — staging.api.example.com, Production — api.example.com. Wszystkie trzy dziedziczą wspólny Shared.xcconfig przez #include.

Kluczowym parametrem różniącym środowiska jest PRODUCT_BUNDLE_IDENTIFIER. Dla Dev: com.example.myapp.dev, dla Staging: com.example.myapp.staging, dla Production: com.example.myapp. Różne bundle ID pozwalają zainstalować wszystkie trzy wersje na jednym urządzeniu jednocześnie. Różnią się także CODE_SIGN_IDENTITY (Apple Development dla Dev, Apple Distribution dla Production) i PROVISIONING_PROFILE_SPECIFIER.

Do przekazywania wartości do kodu używa się INFOPLIST_PREFIX_HEADER lub OTHER_SWIFT_FLAGS z preprocesorem -D. W Swift nie ma preprocesora, dlatego używa się Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEV. W kodzie: #if DEV; #elseif STAGING; #else; #endif. Dla Objective-C używa się GCC_PREPROCESSOR_DEFINITIONS. Pozwala to kompilować różny kod dla różnych środowisk bez zmiany źródeł.

text
// --- 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 API przez Info.plist — wartość jest podstawiana
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 i Info.plist: przekazywanie wartości

Wartości z .xcconfig można przekazywać do Info.plist przez zmienne $(PARAMETER_NAME). Jeśli parametr jest zdefiniowany w .xcconfig (np. API_BASE_URL), można go użyć w Info.plist: <key>ApiBaseUrl</key><string>$(API_BASE_URL)</string>. Na etapie kompilacji Xcode zastępuje $(API_BASE_URL) wartością z .xcconfig. Pozwala to konfigurować aplikację bez zmiany kodu — wystarczy przełączyć schemat.

Parametry .xcconfig używane w Info.plist muszą być publiczne — trafiają do pliku binarnego i są widoczne w zdekompilowanej aplikacji. Dla wartości poufnych (tokeny, hasła) nie używaj .xcconfig — użyj usług takich jak Firebase Remote Config, uruchamianych na serwerze. .xcconfig dla Info.plist nadaje się do: URL serwerów, nazw jednostek, identyfikatorów trackerów, feature flags.

Dostęp do wartości Info.plist w kodzie: Bundle.main.object(forInfoDictionaryKey: "ApiBaseUrl") dla Objective-C/Swift. Jeśli wartość jest ustawiona przez .xcconfig, zostanie podstawiona i dostępna w Bundle main.infoDictionary. Ta metoda jest preferowana nad BuildConfigField (jak w Androidzie), ponieważ Info.plist to standardowy mechanizm iOS, a jego wartości są dostępne dla wszystkich komponentów systemu, w tym extensions, widgetów i Siri Intents.

Często zadawane pytania

Czym .xcconfig różni się od User-Defined Setting w Xcode?

User-Defined Setting to niestandardowy parametr dodany przez UI Build Settings. Działa tak samo jak .xcconfig, ale nie można go wersjonować, komentować ani wykorzystywać między projektami. .xcconfig to plik na dysku, User-Defined Setting to wpis w project.pbxproj.

Czy można używać .xcconfig dla CocoaPods?

Tak, CocoaPods generuje pliki Pods-*.xcconfig dla każdej konfiguracji. Te pliki zawierają ustawienia do podłączenia podów. Pods.xcconfig jest automatycznie dołączany do twojego .xcconfig przez #include w pliku generatora. Nie edytuj Pods.xcconfig ręcznie — jest nadpisywany przy pod install.

Jak uzyskać wartość .xcconfig w kodzie Swift?

Przez Info.plist: zdefiniuj parametr w .xcconfig i użyj $(PARAM) w Info.plist. W kodzie: Bundle.main.infoDictionary["PARAM"]. Dla flag preprocesora użyj SWIFT_ACTIVE_COMPILATION_CONDITIONS i #if CONDITION.

Dlaczego .xcconfig nie działa?

Przyczyny: zmieniłeś wartość w UI Build Settings (UI nadpisuje .xcconfig); plik nie jest podłączony do konfiguracji (sprawdź Project → Info → Configurations); nieprawidłowa ścieżka #include; literówka w nazwie parametru. Diagnostyka: xcodebuild -showBuildSettings pokaże wszystkie aktywne parametry.

Czy .xcconfig jest potrzebny dla projektów SwiftUI?

Tak, .xcconfig nie zależy od frameworka UI. Dla projektów SwiftUI .xcconfig jest również przydatny: zarządzanie bundle ID, wersjami, konfiguracjami środowiska, SWIFT_ACTIVE_COMPILATION_CONDITIONS dla flag funkcji. SwiftUI nie zapewnia alternatywy dla .xcconfig, dlatego zaleca się jego używanie w każdym projekcie.

Podsumowanie

  • .xcconfig — plik tekstowy Build Settings do wersjonowanego zarządzania konfiguracjami Xcode.
  • Dziedziczenie przez #include pozwala budować hierarchię konfiguracji od Base do Production.
  • Składnia obejmuje zmienne $(VAR), dyrektywy warunkowe [sdk=ios*] i komentarze // oraz #.
  • Podłączanie wykonuje się w Project Info → Configurations dla każdej Build Configuration.
  • Środowiska Dev/Staging/Production różnią się bundle ID, certyfikatami i URL API.
  • Info.plist otrzymuje wartości z .xcconfig przez $(PARAM), udostępniając je w runtime.
  • Zalecenie: całkowicie przejdź na .xcconfig i nie używaj UI Build Settings, aby uniknąć konfliktów.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również