.xcconfig یک فایل پیکربندی Xcode به فرمات «key=value» است که Build Settings پروژه را به صورت متمرکز مدیریت میکند. به جای تغییر دستی پارامترها در UI Xcode برای هر پیکربندی، توسعهدهندگان آنها را در یک فایل متنی توصیف میکنند که قابل نسخهبندی و استفاده مجدد در پروژههاست. به گزارش Apple Developer Documentation, 2025، استفاده از .xcconfig زمان تنظیم پروژه را تا 70% کاهش میدهد و اختلافات پیکربندی را بین توسعهدهندگان برطرف میکند. فایلهای .xcconfig میتوانند از یکدیگر ارثبرداری کنند و زنجیرهای از پیکربندیها تشکیل دهند.
نکات کلیدی
.xcconfig (Xcode Configuration File) — یک فایل متنی است که Build Settings را به فرمات PARAMETER_NAME = value دارد. فایلهای .xcconfig برای مدیریت متمرکز پیکربندیهای ساخت Xcode استفاده میشوند: آنها ویرایش دستی زمینهها را در Build Settings UI جایگزین میکنند. هر .xcconfig به Build Configuration (Debug، Release) یا کل پروژه متصل است و میتواند هر تنظیم ساختی را بازنویسی کند: 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 مقدار را در مرحله ساخت با جایگزینی مقادیر فعلی متغیرها محاسبه میکند. متغیرهای سیستمی نیز پشتیبانی میشوند: 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 مهم است. .xcconfig سطح پروژه پارامترهای پیشفرض را برای همه targetها تنظیم میکند. .xcconfig سطح target آنها را برای یک target مشخص بازنویسی میکند. اگر پارامتری در .xcconfig سطح target مشخص نشده باشد، مقدار سطح پروژه استفاده میشود. اگر آنجا هم مشخص نشده باشد — از project.pbxproj. قاعده عملی: پارامترهای عمومی (ساخت، نسخهها) را در سطح پروژه قرار دهید و ویژگیهای target (bundle identifier، provisioning) را در سطح target.
در صورت تعارض بین .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 استفاده میکند. هر سه از طریق #include از Shared.xcconfig مشترک ارث میبرند.
پارامتر کلیدی که محیطها را متمایز میکند PRODUCT_BUNDLE_IDENTIFIER است. برای Dev: com.example.myapp.dev، برای Staging: com.example.myapp.staging، برای Production: com.example.myapp. bundle IDهای مختلف امکان نصب هر سه نسخه را به صورت همزمان روی یک دستگاه فراهم میکنند. CODE_SIGN_IDENTITY (برای Dev Apple Development، برای Production Apple Distribution) و 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
// URL API از طریق 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 را میتوان از طریق متغیرهای $(PARAMETER_NAME) به Info.plist انتقال داد. اگر پارامتری در .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 flagها.
در کد به مقادیر 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 تولید میکند. این فایلها شامل تنظیمات برای اتصال podها هستند. Pods.xcconfig از طریق #include در فایل تولیدکننده به طور خودکار به .xcconfig شما متصل میشود. 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 برای feature flagها. SwiftUI جایگزینی برای .xcconfig ارائه نمیدهد، بنابراین توصیه میشود در هر پروژهای از آن استفاده کنید.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید