821 votes

Remplacement des #ifdef dans le langage Swift

En C/C++/Objective C, vous pouvez définir une macro en utilisant les préprocesseurs du compilateur. De plus, vous pouvez inclure/exclure certaines parties du code en utilisant les préprocesseurs du compilateur.

#ifdef DEBUG
    // Debug-only code
#endif

Existe-t-il une solution similaire en Swift ?

1 votes

Comme idée, vous pourriez mettre ceci dans vos en-têtes de pontage obj-c..

60 votes

Vous devriez vraiment attribuer une réponse car vous avez le choix entre plusieurs réponses et cette question vous a valu beaucoup de votes positifs.

0 votes

@Userthatisnotauser vous avez totalement manqué le point. Vous posez une question, vous obtenez de bonnes réponses - choisissez-en une. N'ignorez pas le temps et l'effort.

4voto

Adam Smaka Points 2044
func inDebugBuilds(_ code: () -> Void) {
    assert({ code(); return true }())
}

Source :

2voto

Warren Stringer Points 11

Cela s'appuie sur Jon Willis qui repose sur assert, qui n'est exécuté que dans les compilations Debug :

func Log(_ str: String) { 
    assert(DebugLog(str)) 
}
func DebugLog(_ str: String) -> Bool { 
    print(str) 
    return true
}

Mon cas d'utilisation est la journalisation des déclarations d'impression. Voici un benchmark pour la version Release sur iPhone X :

let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
    Log (" unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: \(time2-time1)" )

des empreintes :

Log: 0.0

On dirait que Swift 4 élimine complètement l'appel de fonction.

0voto

Skron31 Points 11

Mise à jour de Swift 5 pour réponse de matt

let dic = ProcessInfo.processInfo.environment
if dic["TRIPLE"] != nil {
// ... do your secret stuff here ...
}

-2voto

Benjamin Gruenbaum Points 51406

Mise à jour - dans les versions plus récentes, il existe une contrepartie directe - voir la réponse de Jean pour plus de détails. Je garde ceci comme référence historique.


Il n'y a pas de contrepartie directe.

L'un des cas d'utilisation courants de la #ifdef DEBUG dans mon code est de faire des assertions à ce sujet.

Pour un cas d'utilisation courant, vous utiliserez la nouvelle fonction globale assert en Swift :

Extrait de "The Swift Programming Language" :

let age = -3;
assert(age >=0, "A person's age cannot be less than zero")

Cela ne se déclenchera que lors de l'exécution dans un environnement de débogage (comme lors de la construction et de l'exécution dans xcode).

Pour une solution plus générale, vous pouvez toujours définir un paramètre global DEBUG et l'utiliser dans votre code :

let debug = true
if debug {
    // debug only code
}

Bien que je n'aie pas encore de preuve à l'appui, étant donné le backend de LLVM, vous pouvez être quasiment certain que le code qui est déclaré avec des constantes (c'est-à-dire avec let et non avec var ) permettra au compilateur d'exécuter DCE (dead code elimination) et d'éliminer ce code de la production dès que vous modifiez sa valeur.

De plus, vous pouvez toujours utiliser le cpp (préprocesseur C) sur du code non-C en écrivant simplement :

cpp myfile

Ce qui produit votre code après #ifdef etc., remplacées par des valeurs Swift appropriées. Je pense que cela devrait être rarement requis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X