En C / C ++ / Objective C, vous pouvez définir une macro à l'aide de préprocesseurs de compilateur. De plus, vous pouvez inclure / exclure certaines parties de code à l'aide de préprocesseurs de compilateur.
#ifdef DEBUG
// Debug-only code
#endif
Existe-t-il une solution similaire dans Swift?
Réponses:
Oui, vous pouvez le faire.
Dans Swift, vous pouvez toujours utiliser les macros de préprocesseur "# if / # else / # endif" (bien que plus contraintes), selon les documents Apple . Voici un exemple:
Maintenant, vous devez cependant placer le symbole "DEBUG" ailleurs. Réglez-le dans la section "Swift Compiler - Custom Flags", ligne "Other Swift Flags". Vous ajoutez le symbole DEBUG avec l'
-D DEBUG
entrée.Comme d'habitude, vous pouvez définir une valeur différente dans Debug ou dans Release.
Je l'ai testé en vrai code et cela fonctionne; il ne semble cependant pas être reconnu dans une cour de récréation.
Vous pouvez lire mon post original ici .
REMARQUE IMPORTANTE:
-DDEBUG=1
ne fonctionne pas. Fonctionne uniquement-D DEBUG
. Le compilateur semble ignorer un indicateur avec une valeur spécifique.la source
-D DEBUG
comme indiqué ci-dessus, vous devez également définirDEBUG=1
dansApple LLVM 6.0 - Preprocessing
->Preprocessor Macros
.-DDEBUG
de cette réponse: stackoverflow.com/a/24112024/747369 .DEBUG=1
àPreprocessor Macros
, si vous ne voulez pas l'utiliser dans le code Objective-C.Comme indiqué dans Apple Docs
J'ai réussi à réaliser ce que je voulais en utilisant des configurations de construction personnalisées:
Voici comment vous vérifiez la cible:
Testé avec Swift 2.2
la source
-DLOCAL
, sur mon#if LOCAl #else #endif
, il tombe dans la#else
section. J'ai dupliqué la cible d'origineAppTarget
et je l'ai renommée pourAppTargetLocal
définir son indicateur personnalisé.#if LOCAL
le résultat souhaité lorsque je cours avec le simulateur et tombe#else
pendant les tests. Je veux que ça tombe#if LOCAL
aussi pendant les tests.Dans de nombreuses situations, vous n'avez pas vraiment besoin d'une compilation conditionnelle ; vous avez juste besoin d'un comportement conditionnel que vous pouvez activer et désactiver. Pour cela, vous pouvez utiliser une variable d'environnement. Cela a l'énorme avantage que vous n'avez pas à recompiler.
Vous pouvez définir la variable d'environnement et l'activer ou la désactiver facilement dans l'éditeur de schéma:
Vous pouvez récupérer la variable d'environnement avec NSProcessInfo:
Voici un exemple concret. Mon application fonctionne uniquement sur l'appareil, car elle utilise la bibliothèque musicale, qui n'existe pas sur le simulateur. Comment, alors, prendre des captures d'écran sur le simulateur pour des appareils que je ne possède pas? Sans ces captures d'écran, je ne peux pas me soumettre à l'AppStore.
J'ai besoin de fausses données et d'une manière différente de les traiter . J'ai deux variables d'environnement: une qui, lorsqu'elle est activée, indique à l'application de générer les fausses données à partir des données réelles lors de l'exécution sur mon appareil; l'autre qui, lorsqu'il est allumé, utilise les fausses données (pas la bibliothèque musicale manquante) lors de l'exécution sur le simulateur. Activer / désactiver chacun de ces modes spéciaux est facile grâce aux cases à cocher des variables d'environnement dans l'éditeur de schéma. Et le bonus est que je ne peux pas les utiliser accidentellement dans ma build App Store, car l'archivage n'a pas de variables d'environnement.
la source
Un changement majeur de
ifdef
remplacement est venu avec Xcode 8. c'est-à-dire l'utilisation des conditions de compilation active .Reportez-vous à la section Création et liaison dans la note de publication de Xcode 8 .
Nouveaux paramètres de construction
Nouveau paramètre:
SWIFT_ACTIVE_COMPILATION_CONDITIONS
Auparavant, nous devions déclarer vos indicateurs de compilation conditionnelle sous OTHER_SWIFT_FLAGS, en pensant à ajouter «-D» au paramètre. Par exemple, pour compiler conditionnellement avec une valeur MYFLAG:
La valeur à ajouter au paramètre
-DMYFLAG
Il ne nous reste plus qu'à passer la valeur MYFLAG au nouveau paramètre. Il est temps de déplacer toutes ces valeurs de compilation conditionnelle!
Veuillez vous référer au lien ci-dessous pour plus de fonctionnalités de paramètres de construction rapide dans Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
la source
Depuis Swift 4.1, si tout ce dont vous avez besoin est simplement de vérifier si le code est construit avec une configuration de débogage ou de publication, vous pouvez utiliser les fonctions intégrées:
_isDebugAssertConfiguration()
(vrai lorsque l'optimisation est définie sur-Onone
)(non disponible sur Swift 3+)_isReleaseAssertConfiguration()
(vrai lorsque l'optimisation est définie sur-O
)_isFastAssertConfiguration()
(vrai lorsque l'optimisation est définie sur-Ounchecked
)par exemple
Par rapport aux macros de préprocesseur,
-D DEBUG
indicateur personnalisé pour l'utiliser✗ Non documenté, ce qui signifie que la fonction peut être supprimée dans n'importe quelle mise à jour (mais elle devrait être sécurisée par AppStore car l'optimiseur les transformera en constantes)
@testable
attribut , le sort est incertain pour le futur Swift.✗ L'utilisation de if / else générera toujours un avertissement "ne sera jamais exécuté".
la source
if _isDebugAssertConfiguration()
sera évaluéif false
en mode release etif true
est en mode debug.Xcode 8 et supérieur
Utiliser des conditions de compilation actives paramètre dans Paramètres de compilation / Compilateur Swift - Indicateurs personnalisés .
ALPHA
,BETA
etc.Ensuite, vérifiez-le avec des conditions de compilation comme celle-ci:
la source
Il n'y a pas de préprocesseur Swift. (D'une part, la substitution de code arbitraire rompt la sécurité de type et de mémoire.)
Swift inclut des options de configuration au moment de la construction, donc vous pouvez inclure conditionnellement du code pour certaines plates-formes ou styles de construction ou en réponse aux indicateurs que vous définissez avec
-D
les arguments du compilateur. Contrairement à C, cependant, une section conditionnellement compilée de votre code doit être syntaxiquement complète. Il y a une section à ce sujet dans Utilisation de Swift avec Cocoa et Objective-C .Par exemple:
la source
INT_CONST
n'importe où unfloat
serait accepté. Swift ne le permettrait pas. De plus, si vous pouviez le fairevar floatVal = INT_CONST
inévitablement, cela tomberait en panne quelque part plus tard lorsque le compilateur attend unInt
mais vous l'utilisez commeFloat
(le type defloatVal
serait inféré commeInt
). 10 lancers plus tard et son nettoyant juste pour enlever les macros ...Mes deux cents pour Xcode 8:
a) Un indicateur personnalisé utilisant le
-D
préfixe fonctionne bien, mais ...b) Utilisation plus simple:
Dans Xcode 8, il y a une nouvelle section: "Conditions de compilation actives", déjà avec deux lignes, pour le débogage et la publication.
Ajoutez simplement votre définition SANS
-D
.la source
-D
.Constante isDebug basée sur les conditions de compilation actives
Une autre solution, peut-être plus simple, qui se traduit toujours par un booléen que vous pouvez passer à des fonctions sans peppering des
#if
conditions dans votre base de code consiste à définirDEBUG
comme l'une des cibles de génération de votre projetActive Compilation Conditions
et à inclure ce qui suit (je le définis comme une constante globale):Constante isDebug basée sur les paramètres d'optimisation du compilateur
Ce concept s'appuie sur la réponse de kennytm
Le principal avantage lors de la comparaison avec kennytm est qu'il ne repose pas sur des méthodes privées ou non documentées.
Dans Swift 4 :
Par rapport aux macros de préprocesseur et à la réponse de kennytm ,
-D DEBUG
indicateur pour l'utiliser✓ Documenté , ce qui signifie que la fonction suivra les modèles de libération / dépréciation d'API normaux.
✓ L'utilisation de if / else ne générera pas d' avertissement "ne sera jamais exécuté".
la source
La réponse de Moignans ici fonctionne bien. Voici une autre paix d'informations au cas où cela aiderait,
Vous pouvez annuler les macros comme ci-dessous,
la source
Dans les projets Swift créés avec Xcode version 9.4.1, Swift 4.1
fonctionne par défaut car dans les macros du préprocesseur, DEBUG = 1 a déjà été défini par Xcode.
Vous pouvez donc utiliser #if DEBUG "out of box".
Soit dit en passant, comment utiliser les blocs de compilation de conditions en général est écrit dans le livre d'Apple The Swift Programming Language 4.1 (la section Instructions de contrôle du compilateur) et comment écrire les indicateurs de compilation et ce qui est l'équivalent des macros C dans Swift est écrit en un autre livre d'Apple Using Swift with Cocoa and Objective C (dans la section Directives du préprocesseur)
J'espère qu'à l'avenir, Apple rédigera le contenu plus détaillé et les index de leurs livres.
la source
XCODE 9 ET PLUS
la source
Après avoir défini
DEBUG=1
vosGCC_PREPROCESSOR_DEFINITIONS
paramètres de construction, je préfère utiliser une fonction pour effectuer ces appels:Et ensuite, insérez dans cette fonction tout bloc que je souhaite omettre dans les versions de débogage:
L'avantage par rapport à:
Est-ce que le compilateur vérifie la syntaxe de mon code, donc je suis sûr que sa syntaxe est correcte et se construit.
la source
! [Dans Xcode 8 et supérieur, allez dans le paramètre de construction -> recherchez des drapeaux personnalisés] 1
Dans du code
la source
La source
la source
@inlinable
devantfunc
et ce serait la manière la plus élégante et idiomatique pour Swift. Dans les versions, votrecode()
bloc sera optimisé et complètement éliminé. Une fonction similaire est utilisée dans le propre framework NIO d'Apple.Cela s'appuie sur la réponse de Jon Willis qui s'appuie sur assert, qui n'est exécuté que dans les compilations de débogage:
Mon cas d'utilisation est pour la journalisation des relevés d'impression. Voici une référence pour la version Release sur iPhone X:
impressions:
On dirait que Swift 4 élimine complètement l'appel de fonction.
la source