Ich möchte alle println()
Aufrufe in meinem Swift-Code global ignorieren, wenn ich mich nicht in einem Debug-Build befinde. Ich kann keine robuste Schritt-für-Schritt-Anleitung dafür finden und würde mich über eine Anleitung freuen. Gibt es eine Möglichkeit, dies global zu tun, oder muss ich alle println()
mit #IF DEBUG/#ENDIF
Aussagen umgeben?
83
Antworten:
Der einfachste Weg ist, Ihre eigene globale Funktion vor die von Swift zu stellen
println
:Wenn es Zeit ist, die Protokollierung zu beenden, kommentieren Sie einfach den Hauptteil dieser Funktion aus:
Oder Sie können es automatisch machen, indem Sie eine Bedingung verwenden:
BEARBEITEN In Swift 2.0
println
wird in geändertprint
. Leider hat es jetzt einen variadischen ersten Parameter; Das ist cool, aber es bedeutet, dass Sie es nicht einfach überschreiben können, da Swift keinen "splat" -Operator hat, sodass Sie keine Variable im Code übergeben können (sie kann nur wörtlich erstellt werden). Sie können jedoch eine reduzierte Version erstellen, die funktioniert, wenn Sie wie gewöhnlich nur einen Wert drucken:In Swift 3 müssen Sie die externe Bezeichnung des ersten Parameters unterdrücken:
quelle
println()
nicht im Release-Modus ausgeführt wird.println
geändert aufprint
. Der Grund, warum es bei Ihnen nicht funktioniert, ist, dass Ihreprint
Definition nicht mit der von Swift übereinstimmt, sodass Sie sie nicht überschreiben. Es gibt ein kleines Problem, da Swift, wie schon oft bemerkt, keinen Splat-Operator hat, sodass Sie die Variadik nicht übergeben können. Aber es funktioniert gut für einen Artikel, den Sie als übergeben könnenitems[0]
.Aktualisiert für Swift 4.x:
Mit Swift 2.0 / 3.0 und Xcode 7/8, die jetzt nicht mehr in der Beta sind, wurden einige Änderungen an der Deaktivierung der Druckfunktion in Release-Builds vorgenommen.
Es gibt einige wichtige Punkte, die von @matt und @Nate Birkholz oben erwähnt wurden und die noch gültig sind.
Die
println()
Funktion wurde ersetzt durchprint()
Um das
#if DEBUG
Makro zu verwenden, müssen Sie den "Swift Compiler - Benutzerdefinierte Flags - Andere Flags" definieren, um den Wert zu enthalten-D DEBUG
Ich würde empfehlen, das zu überschreiben
Swift.print()
Funktion im globalen Bereich zu damit Sie dieprint()
Funktion wie gewohnt in Ihrem Code verwenden können, aber die Ausgabe für Nicht-Debug-Builds wird entfernt. Hier ist eine Funktionssignatur, die Sie im globalen Bereich hinzufügen können, um dies in Swift 2.0 / 3.0 zu tun:Hinweis: Wir haben das Standardtrennzeichen hier als Leerzeichen und das Standardterminator als Zeilenumbruch festgelegt. Sie können dies in Ihrem Projekt anders konfigurieren, wenn Sie möchten.
Hoffe das hilft.
Aktualisieren:
Es ist normalerweise vorzuziehen, diese Funktion in den globalen Bereich zu stellen, damit sie vor Swifts
print
Funktion steht. Ich finde, dass der beste Weg, dies zu organisieren, darin besteht, Ihrem Projekt eine Dienstprogrammdatei (wie DebugOptions.Swift) hinzuzufügen, in der Sie diese Funktion im globalen Bereich platzieren können.Ab Swift 3 ist der
++
Bediener veraltet. Ich habe das obige Snippet aktualisiert, um diese Änderung widerzuspiegeln.quelle
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Das Problem bei all diesen Ansätzen, einschließlich meiner, besteht darin, dass sie den Aufwand für die Bewertung der
print
Argumente nicht verringern . Egal welche von ihnen Sie verwenden, dies wird teuer:Die einzig vernünftige Lösung besteht darin, den eigentlichen Druckaufruf in eine bedingte Kompilierung zu verpacken (nehmen wir an, dass dies
DEBUG
nur für Debug-Builds definiert ist):Das und nur das verhindert, dass
myExpensiveFunction
es in einem Release-Build aufgerufen wird.Sie können die Auswertung jedoch mithilfe der automatischen Schließung um eine Ebene zurückschieben . So können Sie meine Lösung (dies ist Swift 3) folgendermaßen umschreiben:
Dies löst das Problem nur für den Fall, dass Sie nur eine Sache drucken, was normalerweise zutrifft. Das liegt daran
item()
, dass im Release-Modus nicht aufgerufen wird.print(myExpensiveFunction())
Dies ist nicht mehr teuer, da der Anruf ohne Auswertung in einen Abschluss eingeschlossen wird und im Freigabemodus überhaupt nicht ausgewertet wird.quelle
@autoclosure
?print
Aussagen in meinem Versandcode zu belassen, aber das unterscheidet sich von dem, worum es in meiner Antwort hier geht. Eineprint
Anweisungsausgabe wird in Ihrem Xcode-unabhängigen Release-Build nicht an die Konsole gesendet, sie wird jedoch weiterhin ausgewertet . Daher bleibt es hilfreich zu wissen, wie diese Auswertung unterdrückt werden kann, falls sie teuer ist oder unerwünschte Nebenwirkungen aufweist.Wie bereits erwähnt, bin ich Student und brauche Dinge, die etwas klarer definiert sind, um mitzumachen. Nach vielen Recherchen musste ich folgende Reihenfolge einhalten:
Klicken Sie oben im Datei-Navigator links im Xcode-Projektfenster auf den Projektnamen. Dies ist eine Zeile mit dem Namen des Projekts, der Anzahl der Build-Ziele und der iOS SDK-Version.
Wählen Sie die Registerkarte Build Settings und scrollen Sie zum Abschnitt " Swift Compiler - Custom Flags " unten. Klicken Sie auf den Abwärtspfeil neben Andere Flags , um den Abschnitt zu erweitern.
Klicken Sie auf die Debug- Zeile, um sie auszuwählen. Platzieren Sie den Mauszeiger über der rechten Seite der Linie und doppelklicken Sie. Eine Listenansicht wird angezeigt. Klicken Sie unten links in der Listenansicht auf die Schaltfläche + , um einen Wert hinzuzufügen. Ein Textfeld wird aktiv.
Geben Sie im Textfeld den Text ein
-D DEBUG
und drücken Sie die Eingabetaste , um die Zeile festzuschreiben.Fügen Sie Ihrem Projekt eine neue Swift-Datei hinzu. Sie möchten eine benutzerdefinierte Klasse für die Datei erstellen. Geben Sie daher Text wie folgt ein:
Ich hatte Probleme, die Klasse heute von Xcode zu akzeptieren, daher ist der Init möglicherweise etwas schwerer als nötig.
Jetzt müssen Sie Ihre benutzerdefinierte Klasse in jeder Klasse referenzieren, in der Sie die neue benutzerdefinierte Funktion anstelle von
println()
Add this als Eigenschaft in jeder anwendbaren Klasse verwenden möchten:Jetzt können Sie alle Instanzen von
println()
durch ersetzenlogFor.DLog()
. Die Ausgabe enthält auch den Namen der Funktion, in der die Zeile aufgerufen wurde.Beachten Sie, dass ich innerhalb von Klassenfunktionen die Funktion nur aufrufen konnte, wenn ich eine Kopie der Funktion als Klassenfunktion in dieser Klasse erstellt habe, und dass
println()
die Eingabe auch etwas flexibler ist, sodass ich sie nicht in jedem Fall in verwenden konnte mein Code.quelle
Hier ist eine Funktion, die ich benutze und die in Swift 3 perfekt funktioniert:
Hier ist ein Beispiel für die Ausgabe, die es generiert:
Erläuterung:
Mit dem grünen Häkchen können Sie Ihre Drucknachrichten (gLog) schnell in der Konsole anzeigen, wo sie manchmal in einem Meer anderer Nachrichten verloren gehen können
den Zeit- / Datumsstempel
der Thread, auf dem es ausgeführt wird - in meinem Fall ist es entweder der MainThread (den ich UI nenne) oder nicht der MainThread (den ich BG nenne, für den Hintergrund-Thread)
Der Name der Datei, in der sich die gLog-Nachricht befindet
Die Funktion in der Datei, in der sich die gLog-Nachricht befindet
die Zeilennummer der gLog-Nachricht
Die eigentliche gLog-Nachricht, die Sie ausdrucken möchten
Hoffe, das ist nützlich für jemand anderen!
quelle
Swift 4.2
Der folgende Code funktioniert perfekt für mich:
Diese Funktion spiegelt den Standard-Swift-Druck wider, sodass Sie ihn genauso verwenden können
print("hello world")
(Sie müssen weder die Trennzeichen- noch die Abschlusszeichenparameter eingeben). Durch das Drucken jedes Elements auf diese Weise werden außerdem störende Array-Klammern um die Druckanweisungen entfernt, die angezeigt werden, wenn Sie direktitems
in das Element übergehenSwift.print()
.Für jemanden, der relativ neu in Swift ist, mag man sich fragen, was zum Teufel
$0
ist. Es stellt nur das erste Argument dar, das an denforEach
Block übergeben wird. DieforEach
Aussage könnte auch so geschrieben werden:Wenn Sie interessiert sind,
print
sieht die Swift-Erklärung folgendermaßen aus :Die Dokumente sagen auch, dass das Standardtrennzeichen ein einzelnes Leerzeichen (
" "
) und das Standardterminator ein Zeilenumbruch ("\n"
) ist, sodass meine obige Antwort die genaue Swift-Implementierung widerspiegelt - obwohl ich nie mehr als eine Sache drucke oder Trennzeichen / Terminatoren ändere. Aber wer weiß, vielleicht möchten Sie.quelle
Getestet mit Swift 2.1 & Xcode 7.1.1
Es gibt eine einfache Möglichkeit, alle Druckanweisungen von Release-Versionen auszuschließen, sobald Sie wissen, dass leere Funktionen vom Swift-Compiler entfernt werden .
Randnotiz: In der Ära von Objective-C gab es einen Pre-Parser, mit dem NSLog-Anweisungen vor dem Start des Compilers entfernt werden konnten, wie in meiner Antwort hier beschrieben . Da Swift jedoch keinen Pre-Parser mehr hat, ist dieser Ansatz nicht mehr gültig.
Folgendes verwende ich heute als erweiterte und einfach konfigurierbare Protokollfunktion, ohne mich jemals darum kümmern zu müssen, sie in Release-Builds zu entfernen. Durch Setzen verschiedener Compiler-Flags können Sie auch die protokollierten Informationen nach Bedarf anpassen.
Sie können die Funktion nach Bedarf anpassen. Jeder Vorschlag zur Verbesserung ist willkommen!
Hier setzen Sie die Compiler-Flags:
Eine Beispielausgabe mit allen Flags sieht folgendermaßen aus:
Der Code mit log () sieht folgendermaßen aus:
quelle
Noch einfacher, nachdem Sie sichergestellt haben
-D DEBUG
, dass dieOTHER_SWIFT_FLAGS
Debug-Build-Einstellungen festgelegt sind:quelle
XCode 8 hat einige neue Build-Einstellungen eingeführt .
Insbesondere macht einer, auf den Bezug genommen wird,
Active Compilation Conditions
auf ähnliche Weise wie die Einstellungen für andere Flags .Gemäß XCode 8 (getestet in 8.3.2) erhalten Sie dies standardmäßig:
Ohne Konfiguration können Sie also Folgendes schreiben:
Ich empfehle Ihnen dringend, wenn Sie diesen Ansatz ausgiebig verwenden, eine Klasse / Struktur / Funktion zu erstellen, die diese Protokollierungslogik umschließt. Vielleicht möchten Sie dies weiter unten verlängern.
quelle
Varun Naharia hat bisher die bessere Lösung. Ich würde seine Antwort mit Riveras ...
-D DEBUG
Flag in den Compiler-Direktiven und erstellen Sie Einstellungen.Fügen Sie dann diesen Code hinzu:
Dieser Code wandelt alles
print
zur Veröffentlichung in nichts um.quelle
Swift 4 Xcode 10.0
Vielleicht könntest du das gebrauchen
Der Grund der Verwendung
@autoclosure
ist, dass, wenn Sie eine Funktion als Nachrichtenparameter übergeben, die Funktion nur im Debug-Modus aufgerufen wird und einen Leistungseinbruch verursacht.Im Gegensatz zur
Swift.print(_ items: Any..., separator: String = default, terminator: String = default)
Funktion hat meine Lösung nur einen Parameter, da in den meisten Fällen nicht mehrere Parameter übergeben werden, da die Druckfunktion nur Informationen in der Konsole anzeigt. Wir können die Parameter einfach in String konvertieren :"\(param1)"+"\(param2)"
, richtig? Ich hoffe du magst meine Lösungquelle
Sie können auch einen Haltepunkt verwenden, ihn so einstellen, dass er nach der Auswertung fortgesetzt wird, und die Drucknachricht in den Haltepunkt schreiben!
quelle
Sie könnten definieren,
debug_println
wessen Inhalt ungefähr sein würde:quelle
Meine Lösung besteht darin, diesen Code vor dem Unterricht in AppDelegate zu verwenden
quelle
Für meine Lösung mache ich es einfach
dann, um es zu zeigen, rufen Sie einfach an
quelle
Am Ende habe ich Folgendes verwendet:
Es ist ziemlich kompakt, druckt einige nützliche Informationen (Zeitstempel, schneller Dateiname, Codezeile, Funktionsname) und zumindest in meinen Tests konnte ich beim Öffnen im Hex-Editor keine protokollierten Zeichenfolgen in der Anwendungsbinärdatei finden.
quelle
Noch einfacher: Nutzen Sie die Tatsache, dass Asserts aus Release-Builds entfernt werden und nur von dort aus den Druck aufrufen. Dadurch werden alle Protokollaufrufe entfernt (ja, sogar die Aufrufe von Log.da), da sie beim Erstellen für die Freigabe leer sind.
Ich habe aber auch gehört, dass Ausdrucke für Release-Builds entfernt werden, konnte sie aber nicht schriftlich finden. Im Moment verwende ich so etwas
Log
unten. Ich habe eine fleischigere Version auf GitHub mit Emojis (aus Gründen der Lesbarkeit) und Protokollthemen (aus Gründen der Konsistenz):https://github.com/Gatada/JBits/blob/master/Project/Utility/Log.swift
In Code:
Gesehen in dem Xcode Debug - Bereich nur , wenn ein Debug - Build ausgeführt wird :
quelle
Mein Projekt wurde in Ziel C entwickelt, aber seit dem letzten Jahr habe ich begonnen, neuen Code in Swift zusammenzuführen. In der folgenden Swift-Lösung habe ich diesen Code in die konstante Datei "Mein Swift" eingefügt:
quelle