Section 8/181 menit

8. xcconfig: Konfigurasi Build yang Terstruktur

8. xcconfig: Konfigurasi Build yang Terstruktur

xcconfig file memisahkan konfigurasi build dari .xcodeproj — lebih mudah di-review di Git, tidak ada merge conflict.

Struktur xcconfig yang Direkomendasikan

swift
MyApp/
├── Configurations/
│   ├── Base.xcconfig          ← settings yang sama di semua env
│   ├── Debug.xcconfig         ← dev, includes Base
│   ├── Staging.xcconfig       ← staging, includes Base
│   └── Release.xcconfig       ← production, includes Base
swift
// Base.xcconfig
// Tidak ada #include di sini — ini yang di-include yang lain

PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.myapp
PRODUCT_NAME = MyApp
SWIFT_VERSION = 5.0
TARGETED_DEVICE_FAMILY = 1,2
IPHONEOS_DEPLOYMENT_TARGET = 17.0

// Code signing
CODE_SIGN_STYLE = Automatic
DEVELOPMENT_TEAM = ABCDEF1234

// Build settings
ENABLE_BITCODE = NO
SWIFT_COMPILATION_MODE = wholemodule
ENABLE_TESTABILITY = NO
swift
// Debug.xcconfig
#include "Base.xcconfig"

// Override untuk debug
SWIFT_OPTIMIZATION_LEVEL = -Onone
ENABLE_TESTABILITY = YES
DEBUG_INFORMATION_FORMAT = dwarf
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE
GCC_OPTIMIZATION_LEVEL = 0

// Preprocessor macros
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1

// App-specific
BASE_URL = https://api-dev.myapp.com
ANALYTICS_KEY = dev-analytics-key-123
swift
// Release.xcconfig
#include "Base.xcconfig"

SWIFT_OPTIMIZATION_LEVEL = -O
SWIFT_COMPILATION_MODE = wholemodule
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
MTL_ENABLE_DEBUG_INFO = NO
GCC_OPTIMIZATION_LEVEL = s

// Strip debug symbols
STRIP_INSTALLED_PRODUCT = YES
DEAD_CODE_STRIPPING = YES

// App-specific
BASE_URL = https://api.myapp.com
ANALYTICS_KEY = prod-analytics-key-456

Akses xcconfig Values dari Swift

swift
// Baca nilai dari Info.plist yang dibaca dari xcconfig
// Tambahkan ke Info.plist:
// BASE_URL = $(BASE_URL)   ← ini automatic expansion dari xcconfig

extension Bundle {
    var baseURL: URL {
        guard let urlString = infoDictionary?["BASE_URL"] as? String,
              let url = URL(string: urlString) else {
            fatalError("BASE_URL not configured in xcconfig")
        }
        return url
    }
    
    var analyticsKey: String {
        guard let key = infoDictionary?["ANALYTICS_KEY"] as? String else {
            fatalError("ANALYTICS_KEY not configured in xcconfig")
        }
        return key
    }
}

// Penggunaan
let client = APIClient(baseURL: Bundle.main.baseURL)
Analytics.configure(key: Bundle.main.analyticsKey)