Das wurde mir ein paar Mal auf dieser Seite gesagt, aber ich wollte sicherstellen, dass dies wirklich der Fall ist.
Ich hatte erwartet, dass ich NSLog-Funktionsaufrufe in meinem Code verteilen kann und dass Xcode / gcc diese Aufrufe beim Erstellen meiner Release / Distribution-Builds automatisch entfernt.
Sollte ich dies vermeiden? Wenn ja, welche Alternativen sind bei erfahrenen Objective-C-Programmierern am häufigsten?
iphone
objective-c
nslog
jpm
quelle
quelle
Antworten:
Präprozessor-Makros eignen sich hervorragend zum Debuggen. An NSLog () ist nichts auszusetzen, aber es ist einfach, eine eigene Protokollierungsfunktion mit besserer Funktionalität zu definieren. Hier ist die, die ich verwende. Sie enthält den Dateinamen und die Zeilennummer, um das Auffinden von Protokollanweisungen zu erleichtern.
Ich fand es einfacher, diese gesamte Anweisung in den Präfix-Header einzufügen, als in eine eigene Datei. Wenn Sie möchten, können Sie ein komplizierteres Protokollierungssystem erstellen, indem Sie DebugLog mit normalen Objective-C-Objekten interagieren lassen. Beispielsweise könnten Sie eine Protokollierungsklasse haben, die in ihre eigene Protokolldatei (oder Datenbank) schreibt und ein Argument zur Priorität enthält, das Sie zur Laufzeit festlegen können, sodass Debug-Meldungen in Ihrer Release-Version nicht angezeigt werden, Fehlermeldungen jedoch ( Wenn Sie dies tun, können Sie DebugLog (), WarningLog () usw. erstellen.
Oh, und denken Sie daran,
#define DEBUG_MODE
dass es an verschiedenen Stellen in Ihrer Anwendung wiederverwendet werden kann. In meiner Anwendung verwende ich sie beispielsweise, um die Prüfung von Lizenzschlüsseln zu deaktivieren und die Ausführung der Anwendung nur zuzulassen, wenn sie vor einem bestimmten Datum liegt. Auf diese Weise kann ich mit minimalem Aufwand eine zeitlich begrenzte, voll funktionsfähige Beta-Kopie verteilen.quelle
Fügen Sie diese 3 Zeilen am Ende der Datei -prefix.pch ein:
Sie müssen nichts in Ihrem Projekt
DEBUG
definieren , da dies beim Erstellen Ihres Projekts standardmäßig in Ihrer Build-Einstellung definiert wird.quelle
NSLog-Aufrufe können im Produktionscode belassen werden, sollten jedoch nur für wirklich außergewöhnliche Fälle oder Informationen vorhanden sein, die im Systemprotokoll protokolliert werden sollen.
Anwendungen, die das Systemprotokoll verunreinigen, sind ärgerlich und wirken unprofessionell.
quelle
Ich kann die Antwort von Marc Charbonneau nicht kommentieren , daher werde ich dies als Antwort veröffentlichen.
Neben dem Hinzufügen des Makros zu Ihrem vorkompilierten Header können Sie die Target-Build-Konfigurationen verwenden, um die Definition (oder das Fehlen einer Definition) der zu steuern
DEBUG_MODE
.Wenn Sie " Debug " auswählen ,
DEBUG_MODE
wird die aktive Konfiguration definiert und das Makro wird zur vollständigenNSLog
Definition erweitert.Die Auswahl der aktiven Konfiguration " Release " wird nicht definiert
DEBUG_MODE
und IhrNSLog
Ging wird im Release-Build weggelassen.Schritte:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
DEBUG_MODE
ist nicht eingestelltGCC_PREPROCESSOR_DEFINITIONS
Wenn Sie das Zeichen '=' in der Definition weglassen, wird vom Präprozessor eine Fehlermeldung angezeigt
Fügen Sie diesen Kommentar (siehe unten) über der Makrodefinition ein, um Sie daran zu erinnern, woher die
DEBUG_MACRO
Definition stammt.quelle
DEBUG_MODE
undDEBUG_MACRO
sind unkonventionell. Ich habe nur einen VerweisDEBUG_MACRO
auf der Apple-Website gefunden ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ). Vielleicht der StandardDEBUG
undNDEBUG
wäre eine bessere Wahl?NDEBUG
wird von Posix angegeben; währendDEBUG
wird durch Konvention verwendet.EDIT: Die Methode von Marc Charbonneau , auf die ich von sho aufmerksam gemacht wurde , ist weitaus besser als diese.
Ich habe den Teil meiner Antwort gelöscht, der die Verwendung einer leeren Funktion zum Deaktivieren der Protokollierung vorschlug, wenn der Debug-Modus deaktiviert ist. Der Teil, der sich mit dem Festlegen eines automatischen Präprozessormakros befasst, ist weiterhin relevant, bleibt also bestehen. Ich habe auch den Namen des Präprozessor-Makros so bearbeitet, dass er besser zu Marc Charbonneaus Antwort passt.
So erreichen Sie das automatische (und erwartete) Verhalten in Xcode:
Gehen Sie in den Projekteinstellungen zur Registerkarte "Erstellen" und wählen Sie die Konfiguration "Debuggen". Suchen Sie den Abschnitt "Präprozessor-Makros" und fügen Sie ein Makro mit dem Namen hinzu
DEBUG_MODE
....
EDIT: Siehe Marc Charbonneau Antwort für die richtige Art und Weise und Deaktivieren der Protokollierung mit dem aktivieren
DEBUG_MODE
Makro.quelle
Ich stimme Matthew zu. An NSLog im Produktionscode ist nichts auszusetzen. In der Tat kann es für den Benutzer nützlich sein. Das heißt, wenn der einzige Grund, warum Sie NSLog verwenden, das Debuggen ist, sollte dies vor der Veröffentlichung entfernt werden.
Da Sie dies als iPhone-Frage markiert haben, nimmt NSLog außerdem Ressourcen in Anspruch, von denen das iPhone nur wenig hat. Wenn Sie auf dem iPhone NSLoggen , wird Ihre App dadurch weniger Prozessorzeit erhalten. Benutze es weise.
quelle
Die einfache Wahrheit ist, dass NSLog einfach nur langsam ist.
Aber wieso? Um diese Frage zu beantworten, wollen wir herausfinden, was NSLog macht und wie es dann geht.
Was macht NSLog genau?
NSLog macht zwei Dinge:
Es schreibt Protokollnachrichten in die Apple System Logging (ASL) -Funktion. Dadurch können Protokollnachrichten in Console.app angezeigt werden. Außerdem wird überprüft, ob der stderr-Stream der Anwendung zu einem Terminal geleitet wird (z. B. wenn die Anwendung über Xcode ausgeführt wird). In diesem Fall wird die Protokollnachricht in stderr geschrieben (sodass sie in der Xcode-Konsole angezeigt wird).
Das Schreiben an STDERR klingt nicht schwierig. Dies kann mit fprintf und der Stderr-Dateideskriptorreferenz erreicht werden. Aber was ist mit asl?
Die beste Dokumentation, die ich über ASL gefunden habe, ist ein 10-teiliger Blog-Beitrag von Peter Hosey: Link
Ohne zu sehr ins Detail zu gehen, ist das Highlight (was die Leistung betrifft) Folgendes:
Um eine Protokollnachricht an die ASL-Einrichtung zu senden, öffnen Sie grundsätzlich eine Clientverbindung zum ASL-Dämon und senden die Nachricht. ABER - jeder Thread muss eine separate Clientverbindung verwenden. Um Thread-sicher zu sein, öffnet NSLog bei jedem Aufruf eine neue ASL-Client-Verbindung, sendet die Nachricht und schließt die Verbindung.
Ressourcen finden Sie hier und hier .
quelle
Wie in anderen Antworten angegeben, können Sie mit #define ändern, ob NSLog zur Kompilierungszeit verwendet wird oder nicht.
Eine flexiblere Möglichkeit besteht jedoch darin, eine Protokollierungsbibliothek wie Cocoa Lumberjack zu verwenden, mit der Sie ändern können, ob auch zur Laufzeit etwas protokolliert wird.
Ersetzen Sie in Ihrem Code NSLog durch DDLogVerbose oder DDLogError usw., fügen Sie einen #import für die Makrodefinitionen usw. hinzu und richten Sie die Protokollierer ein, häufig in der applicationDidFinishLaunching-Methode.
Um den gleichen Effekt wie NSLog zu erzielen, lautet der Konfigurationscode
quelle
Aus Sicherheitsgründen hängt es davon ab, was protokolliert wird. Wenn
NSLog
(oder andere Protokollierer) vertrauliche Informationen schreiben, sollten Sie den Protokollierer im Produktionscode entfernen.Aus Sicht der Prüfung möchte der Prüfer nicht jede Verwendung von
NSLog
prüfen, um sicherzustellen, dass keine vertraulichen Informationen protokolliert werden. Er / sie fordert Sie einfach auf, den Logger zu entfernen.Ich arbeite mit beiden Gruppen. Wir prüfen Code, schreiben die Codierungshandbücher usw. Unser Handbuch erfordert, dass die Protokollierung im Produktionscode deaktiviert ist. Die internen Teams wissen also, dass sie es nicht versuchen sollen;)
Wir werden auch eine externe App ablehnen, die sich in der Produktion anmeldet, da wir das Risiko eines versehentlichen Verlusts vertraulicher Informationen nicht akzeptieren möchten. Es ist uns egal, was der Entwickler uns sagt. Es ist einfach nicht unsere Zeit wert, nachzuforschen.
Und denken Sie daran, wir definieren "sensibel" und nicht den Entwickler;)
Ich sehe auch eine App, die viel Protokollierung durchführt, als eine App, die zum Implodieren bereit ist. Es gibt einen Grund, warum so viel Protokollierung durchgeführt / benötigt wird und es normalerweise keine Stabilität gibt. Es ist genau dort oben mit 'Watchdog'-Threads, die hängende Dienste neu starten.
Wenn Sie noch nie eine Überprüfung der Sicherheitsarchitektur (SecArch) durchlaufen haben, sehen wir uns diese Dinge an.
quelle
Sie sollten nicht unnötig ausführlich mit printf oder NSLog im Release-Code umgehen. Versuchen Sie nur, ein printf oder NSLog zu erstellen, wenn der App etwas Schlimmes passiert ist, dh ein nicht behebbarer Fehler.
quelle
Beachten Sie, dass NSLogs die Benutzeroberfläche / den Hauptthread verlangsamen können. Es ist am besten, sie aus Release-Builds zu entfernen, sofern dies nicht unbedingt erforderlich ist.
quelle
Ich würde die Verwendung von TestFlight für die Protokollierung (kostenlos) wärmstens empfehlen. Ihre Methode überschreibt NSLog (mithilfe eines Makros) und ermöglicht es Ihnen, die Protokollierung auf ihrem Server, dem Apple System-Protokoll und dem STDERR-Protokoll für alle Ihre vorhandenen Aufrufe von NSLog ein- und auszuschalten. Das Schöne daran ist, dass Sie Ihre Protokollnachrichten weiterhin auf Apps überprüfen können, die für Tester und im App Store bereitgestellte Apps bereitgestellt wurden, ohne dass die Protokolle im Systemprotokoll des Benutzers angezeigt werden. Das Beste aus beiden Welten.
quelle