Τα Active Compilation Conditions είναι σημαίες που μεταβιβάζονται στον μεταγλωττιστή κατά τη φάση κατασκευής και επιτρέπουν την συμπερίληψη ή αποκλεισμό συγκεκριμένων τμημάτων κώδικα από το τελικό δυαδικό αρχείο. Σύμφωνα με τα Apple Developer Documentation (2026), η Swift υποστηρίζει Active Compilation Conditions μέσω του κλειδιού OTHER_SWIFT_FLAGS και της οδηγίας #if. Active Compilation Conditions δίνουν στους προγραμματιστές τη δυνατότητα να δημιουργούν διαφορετικές εκδόσεις κώδικα για εντοπισμό σφαλμάτων, δοκιμές και παραγωγή χωρίς ελέγχους χρόνου εκτέλεσης.
Κύρια σημεία
Active Compilation Conditions είναι σημαίες μεταγλώττισης που καθορίζουν το σύνολο των ενεργών οδηγιών προεπεξεργαστή κατά τη φάση κατασκευής. Σε αντίθεση με τις σημαίες χρόνου εκτέλεσης (έλεγχος if (isDebug)), οι συνθήκες μεταγλώττισης αποκλείουν φυσικά τον ανενεργό κώδικα από το δυαδικό αρχείο, βελτιώνοντας την απόδοση και μειώνοντας το μέγεθος της εφαρμογής.
Ο μηχανισμός λειτουργεί σε επίπεδο προεπεξεργαστή ή πρώιμων φάσεων μεταγλώττισης: ο μεταγλωττιστής λαμβάνει μια λίστα ενεργών ονομάτων και όταν συναντά την οδηγία #if NAME ελέγχει εάν το NAME βρίσκεται σε αυτή τη λίστα. Εάν το όνομα δεν υπάρχει — ο κώδικας εντός του τμήματος αγνοείται και δεν μεταγλωττίζεται.
Σύμφωνα με το Swift.org Blog (2025), η χρήση Active Compilation Conditions αντί για σημαίες χρόνου εκτέλεσης μειώνει το μέγεθος του δυαδικού release κατά μέσο όρο 12-18% για έργα με προηγμένο σύστημα καταγραφής και εργαλεία εντοπισμού σφαλμάτων. Αυτό είναι ιδιαίτερα κρίσιμο για εφαρμογές κινητών με περιορισμούς μεγέθους αρχείου εγκατάστασης.
Η κύρια διαφορά από την υπό συνθήκη μεταγλώττιση σε επίπεδο προεπεξεργαστή C/C++ — τα Active Compilation Conditions σε Swift και Kotlin λειτουργούν σε επίπεδο AST (Abstract Syntax Tree) του μεταγλωττιστή, όχι σε επίπεδο αντικατάστασης κειμένου. Αυτό τα καθιστά ασφαλέστερα και πιο προβλέψιμα: οποιοδήποτε συντακτικό σφάλμα σε ανενεργό κλάδο #if θα ανιχνευθεί στη φάση ανάλυσης, δεν θα εμφανιστεί κατά τον χρόνο εκτέλεσης.
Μια άλλη σημαντική διαφορά — στη Swift η συνθήκη #if os(iOS) || os(macOS) ελέγχεται στη φάση μεταγλώττισης και λειτουργεί με ονόματα πλατφορμών, όχι με μακροεντολές προεπεξεργαστή. Αυτό εξαλείφει μια ολόκληρη κατηγορία σφαλμάτων που σχετίζονται με λανθασμένη εισαγωγή κειμένου μέσω #define, που είναι πιθανά στον προεπεξεργαστή C/C++. Ο μεταγλωττιστής Swift βλέπει AST, όχι αντικατεστημένο κείμενο, γεγονός που καθιστά τον εντοπισμό σφαλμάτων της υπό συνθήκη μεταγλώττισης πολύ ευκολότερο.
Η Swift υποστηρίζει Active Compilation Conditions μέσω της οδηγίας #if, η οποία δέχεται μια λίστα ονομάτων σημαιών συνδεδεμένων με λογικούς τελεστές &&, || και !. Ο μεταγλωττιστής συμπεριλαμβάνει τον κώδικα εντός #if ... #endif μόνο εάν η συνθήκη είναι αληθής.
Η Swift παρέχει πολλές ενσωματωμένες συνθήκες: DEBUG (αυτόματα ενεργή σε debug build), swift(>=5.0) (έλεγχος έκδοσης μεταγλωττιστή), canImport(UIKit) (έλεγχος διαθεσιμότητας μονάδας) και targetEnvironment(simulator) (έλεγχος περιβάλλοντος). Αυτές οι συνθήκες δεν απαιτούν πρόσθετη ρύθμιση.
// Ενσωματωμένες συνθήκες Swift
#if DEBUG
print("Debug build — η καταγραφή είναι ενεργή")
#endif
#if canImport(UIKit)
import UIKit
let screen = UIScreen.main.bounds
#elseif canImport(AppKit)
import AppKit
let screen = NSScreen.main?.frame
#endif
Ο προγραμματιστής μπορεί να προσθέσει δικές του σημαίες μέσω του Build Setting OTHER_SWIFT_FLAGS στο Xcode. Η σημαία ορίζεται με πρόθεμα -D, για παράδειγμα -DBETA ή -DANALYTICS_ENABLED. Για διαφορετικές διαμορφώσεις (Debug, Release, Staging) μπορούν να οριστούν διαφορετικά σύνολα σημαιών.
// Χειρισμός προσαρμοσμένης σημαίας BETA
#if BETA
let apiEndpoint = "https://beta.api.com"
let isLoggingEnabled = true
#else
let apiEndpoint = "https://api.com"
let isLoggingEnabled = false
#endif
func trackEvent(_ name: String) {
#if ANALYTICS_ENABLED
Analytics.log(name)
#endif
}
Η Swift υποστηρίζει συνθήκες πλατφόρμας: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows). Αυτές οι συνθήκες ελέγχουν την πλατφόρμα-στόχο κατασκευής και επιτρέπουν τη σύνταξη κοινού κώδικα για πολλές πλατφόρμες Apple με τμήματα ειδικά για κάθε πλατφόρμα.
import Foundation
func getDeviceName() -> String {
#if os(iOS)
return UIDevice.current.name
#elseif os(macOS)
return Host.current.name ?? "Unknown"
#else
return "Other platform"
#endif
}
Στο οικοσύστημα Android, τα Active Compilation Conditions υλοποιούνται μέσω του συστήματος BuildConfig, productFlavors και σημαιών στο build.gradle.kts. Η Kotlin δεν έχει άμεσο ανάλογο της οδηγίας #if σε επίπεδο γλώσσας, αλλά προσφέρει εναλλακτικούς μηχανισμούς.
Η πιο κοινή μέθοδος — προσθήκη buildConfigField για κάθε σημαία: buildConfigField("boolean", "BETA", "true"). Αυτά τα πεδία δημιουργούνται στην κλάση BuildConfig για κάθε Build Variant ξεχωριστά. Το πεδίο DEBUG είναι ήδη ενσωματωμένο και αυτόματα true για debug builds.
// build.gradle.kts
android {
buildTypes {
debug {
buildConfigField("boolean", "BETA", "true")
}
release {
buildConfigField("boolean", "BETA", "false")
}
}
}
// Χρήση σε κώδικα Kotlin
if (BuildConfig.BETA) {
enableBetaFeatures()
}
Το Gradle επιτρέπει τη δημιουργία ξεχωριστών καταλόγων sourceSets για κάθε flavor. Για παράδειγμα, src/demo/ και src/full/. Κλάσεις με το ίδιο όνομα σε διαφορετικά sourceSets αντικαθιστούν η μία την άλλη κατά την κατασκευή του αντίστοιχου flavor. Αυτός είναι ένας ισχυρότερος μηχανισμός από τις σημαίες, επειδή μπορούν να αντικατασταθούν ολόκληρες κλάσεις.
// src/demo/java/com/example/Config.kt
object Config {
const val API_URL = "http://demo.api.com"
const val IS_BETA = true
}
// src/full/java/com/example/Config.kt
object Config {
const val API_URL = "https://full.api.com"
const val IS_BETA = false
}
Για Kotlin Multiplatform (KMP) είναι διαθέσιμη η οδηγία expect/actual, η οποία επιτρέπει τη δήλωση αναμενόμενων δηλώσεων στον κοινό κώδικα και την παροχή υλοποιήσεων πλατφόρμας. Αυτός είναι ένας μηχανισμός σε επίπεδο μεταγλώττισης, παρόμοιος σε αποτέλεσμα με τα Active Compilation Conditions — ο ανενεργός κώδικας δεν μεταγλωττίζεται για ακατάλληλες πλατφόρμες.
Τα Active Compilation Conditions χρησιμοποιούνται σε τέσσερα κύρια σενάρια: εντοπισμός σφαλμάτων (αρχεία καταγραφής, επιθεωρητές), δοκιμές A/B (σημαίες λειτουργιών), προσαρμογή πλατφόρμας (κοινός κώδικας iOS/macOS) και αδειοδότηση (δωρεάν/επί πληρωμή εκδόσεις).
Το πιο συνηθισμένο σενάριο — υπό συνθήκη καταγραφή. Σε debug build όλα τα αρχεία καταγραφής γράφονται στην κονσόλα, σε release — κανένα. Η χρήση #if DEBUG ή BuildConfig.DEBUG εγγυάται ότι το δυαδικό release δεν περιέχει καμία κλήση καταγραφέα, ούτε καν inline.
func logRequest(_ url: URL, _ statusCode: Int) {
#if DEBUG
Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
#endif
}
Εάν μια νέα λειτουργία δεν είναι ακόμη έτοιμη για παραγωγή αλλά υπάρχει ήδη στον κώδικα, μπορεί να κρυφτεί πίσω από μια σημαία μεταγλώττισης. Σε αντίθεση με τις runtime feature flags, οι σημαίες μεταγλώττισης δεν επιβαρύνουν την εφαρμογή με ελέγχους και δεν μπορούν να ενεργοποιηθούν από τον χρήστη.
Τα Active Compilation Conditions πρέπει να χρησιμοποιούνται με μέτρο. Ο υπερβολικός αριθμός σημαιών καθιστά τον κώδικα δυσνόητο: ο προγραμματιστής δεν μπορεί να είναι σίγουρος ποιοι κλάδοι μεταγλωττίζονται εκείνη τη στιγμή. Συνιστάται η τεκμηρίωση κάθε σημαίας στο README ή σε ειδικό αρχείο CONFIG.md.
Σε μεγάλα έργα με κατανεμημένη ομάδα, είναι χρήσιμο να εφαρμοστεί αυτόματη επικύρωση σημαιών στο CI. Κάθε pull request πρέπει να περνά από build με όλους τους πιθανούς συνδυασμούς Active Compilation Conditions. Αυτό εγγυάται ότι ο κώδικας κάτω από ανενεργή σημαία δεν έχει σπάσει λόγω αναδιάρθρωσης και κανένας κλάδος υπό συνθήκη μεταγλώττισης δεν έχει παραμείνει ανέλεγκτος μέχρι την κυκλοφορία. Εργαλεία όπως xcresulttool (για iOS) και Gradle Build Scan (για Android) βοηθούν στην αυτοματοποίηση αυτής της διαδικασίας.
Συχνές Ερωτήσεις
#if DEBUG — είναι μια οδηγία μεταγλώττισης: εάν το DEBUG δεν είναι ενεργό, ο κώδικας εντός του τμήματος δεν εισέρχεται στο δυαδικό. if (isDebug) — έλεγχος χρόνου εκτέλεσης: ο κώδικας μεταγλωττίζεται πάντα, η συνθήκη ελέγχεται κατά την εκτέλεση. Το #if δεν αφήνει ίχνη στο release build.
Στις Build Settings του έργου, βρείτε το Other Swift Flags (OTHER_SWIFT_FLAGS) και προσθέστε μια νέα γραμμή με τη σημαία: -DMY_FLAG. Η σημαία θα είναι ορατή στην οδηγία #if MY_FLAG. Μπορείτε να ορίσετε διαφορετικές σημαίες για διαμορφώσεις Debug και Release.
Στην Kotlin/JVM δεν υπάρχει άμεσο αντίστοιχο. Αντί αυτού χρησιμοποιούνται πεδία BuildConfig (έλεγχος χρόνου εκτέλεσης, αλλά το ProGuard μπορεί να αφαιρέσει τον αχρησιμοποίητο κώδικα). Στην Kotlin Multiplatform — η οδηγία expect/actual σε επίπεδο δηλώσεων.
Ναι, η Swift υποστηρίζει λογικούς τελεστές: #if DEBUG && BETA, #if os(iOS) || os(tvOS), #if !RELEASE. Οι συνθήκες μπορούν να ομαδοποιηθούν με παρενθέσεις για σύνθετη λογική. Τα AND και OR λειτουργούν σύμφωνα με τους τυπικούς κανόνες βραχυκυκλώματος.
Η προεπισκόπηση SwiftUI κατασκευάζεται σε ξεχωριστή διεργασία με σημαίες διαφορετικές από τον κύριο στόχο. Το DEBUG μπορεί να μην είναι ενεργό. Λύση: χρησιμοποιήστε targetEnvironment(simulator) για κώδικα προεπισκόπησης ή μεταφέρετε την υπό συνθήκη λογική σε ξεχωριστές μεθόδους.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης