En l'absence de macros de préprocesseur, existe-t-il un moyen de définir des indicateurs spécifiques au schéma pratique au niveau du projet dans le projet Xcode

174

Avant Swift, je définirais un ensemble de schémas pour les versions alpha, bêta et de distribution. Chacun de ces schémas aurait un ensemble de macros qui ont été définies pour contrôler certains comportements au niveau du projet. L'exemple le plus simple est la macro DEBUG = 1 qui est définie par défaut pour tous les projets Xcode dans le schéma par défaut pour la génération Exécuter. On pourrait interroger #ifdef DEBUG ... et prendre des décisions dans le code en conséquence, même en compilant du code non nécessaire.

Il semble que ce type de gating configurationnel ne soit pas aussi simple avec swift, car les macros ne sont pas prises en charge. Quelqu'un peut-il suggérer une approche comparable, je m'en fiche si le code est compilé, en soi. Je voudrais cependant attribuer des fonctionnalités basées sur le schéma de construction.

banDedo
la source

Réponses:

468

Dans Swift, vous pouvez toujours utiliser les macros de préprocesseur «# if / # else / # endif» (bien que plus contraignantes), selon les documents Apple . Voici un exemple:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

Maintenant, vous devez définir le symbole "DEBUG" ailleurs, cependant. Définissez-le dans la section "Compilateur Swift - Drapeaux personnalisés", ligne "Autres drapeaux Swift". Vous ajoutez le symbole DEBUG avec l' -D DEBUGentrée.

(Paramètres de construction -> Compilateur Swift - Drapeaux personnalisés) entrez la description de l'image ici

Comme d'habitude, vous pouvez définir une valeur différente lors du débogage ou de la version Release.

Je l'ai testé en vrai code; il ne semble pas être reconnu dans une cour de récréation.

Jean Le Moignan
la source
5
Notez que vous pouvez également utiliser les lignes #elseif pour ajouter plus de tests. Chose intéressante, vous pouvez accéder à la définition mais n'en extraire rien; autrement dit, définissez -DDEBUG = 5 (ou = "FOO"), puis essayez de l'imprimer avec "println (DEBUG is (DEBUG)". Cette ligne ne génère aucune erreur, mais ne fait rien.
David H
10
Remarque: "Paramètres intégrés -> Compilateur Swift -> Drapeaux personnalisés" non visible dans les paramètres de construction "Basique". Doit afficher "Tous" les paramètres de construction pour qu'il apparaisse.
lévibostien
7
@EugeneDubinin probablement parce que vous devez vous assurer que cela $(inherited)est utilisé dans les paramètres cibles pour hériter des paramètres du projet.
DanSkeel
2
@DanSkeel belle prise, l'ajout $(inherited)rend mon commentaire hors de propos, merci!
Yevhen Dubinin
10
Dans Xcode 8, il existe désormais également un paramètre "Conditions de compilation actives" dans la section "Compilateur Swift - Drapeaux personnalisés". Vous pouvez ajouter des drapeaux ici sans avoir besoin du -D
Marcus
32

Nous avons rencontré un problème avec le fait de ne pas vouloir définir d'indicateurs de compilateur rapides parce que nous ne voulions pas avoir à les définir et à les maintenir à jour pour différentes cibles, etc. De plus, dans notre base de code mixte, nous ne voulions pas nous souvenir pour définir nos drapeaux de manière appropriée tout le temps pour chaque langue.

Pour le nôtre, nous avons déclaré un fichier dans ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

Dans le .m

PreProcessorMacros.m

#ifdef DEBUG
    BOOL const DEBUG_BUILD = YES;
#else
    BOOL const DEBUG_BUILD = NO;
#endif

Ensuite, dans votre en-tête de pont Objective-C

#import "PreProcessorMacros.h"

Maintenant, utilisez ceci dans votre base de code Swift

if DEBUG_BUILD {
    println("debug")
} else {
    println("release")
}

C'est certainement une solution de contournement, mais cela a résolu notre problème, je l'ai donc publié ici dans l'espoir que cela vous aidera. Il ne vise pas à suggérer que les réponses existantes sont invalides.

Logan
la source
11
L'intérêt des macros est de changer le code en fonction de la configuration de construction. Vous ramenez le if au runtime, vous n'avez pas besoin de macro pour cela.
Berik
18
@Berik - J'ai publié une solution valable dans l'espoir qu'elle pourrait également aider d'autres personnes essayant de résoudre un aspect de ce problème, en particulier dans les projets multilingues. Si votre problème nécessite de ne pas compiler de code spécifique, c'est bien. Un commentaire convient également, en particulier lorsqu'il explique à certains pourquoi ce n'est peut-être pas la solution pour eux. Demander également de noter dans la réponse les limites de cette approche. Le vote négatif est inutile et décourage les solutions alternatives qui pourraient être utiles à d'autres pour résoudre des problèmes similaires. De plus, op dit "Je m'en fiche si le code est compilé".
Logan
5

Solution plus rapide à la méthode Logans. Situé -D DEBUGdans Other Swift FlagsdeSwift Compiler - Custom Flags section dans les paramètres de construction de votre cible.

Ensuite, déclarez la méthode suivante dans la portée globale:

#if DEBUG
let isDebugMode = true
#else
let isDebugMode = false
#endif

Maintenant, utilisez-le comme

if isDebugMode {
    // Do debug stuff
}
Sahil Kapoor
la source
1

Pour moi, définissez l'élément de débogage de « Condition de compilation active » sur «DEBUG» a fonctionné.

Ensuite, l'utilisation de la clé DEBGU fonctionne dans #IF DEBUG fonctionne en mode débogage et #ELSE en mode version:

  1. Sélectionnez votre cible,
  2. Dans l'onglet Paramètres de construction, recherchez "Condition de compilation active",
  3. Définissez la valeur de son élément "Debug" sur "YourKeyWord",
  4. Utilisez simplement comme suit:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
Marjan Basiri
la source
0

Je travaille dans une base de code de langage mixte où le code obj-c utilise une macro pour envoyer des messages de débogage à la console (et cette macro repose sur notre indicateur de préprocesseur de débogage). Je voulais pouvoir appeler cette même macro dans le code swift ...

  1. J'ai créé une méthode de classe sur l'une de mes classes obj-c qui est un wrapper autour de cette macro.
  2. J'ai ajouté cet en-tête obj-c à notre fichier d'en-tête de pont.
  3. Maintenant, mon code swift appelle cette méthode de classe comme un "proxy" de la macro obj-c.

C'est légèrement ennuyeux que je ne puisse pas appeler la macro directement dans le code swift, mais au moins maintenant, je n'ai qu'un seul endroit dans le projet pour m'inquiéter d'activer / désactiver mon indicateur de débogage.

ghostatron
la source