Swift: print () vs println () vs NSLog ()


450

Was ist der Unterschied zwischen print, NSLogund printlnund wann soll ich je benutzen?

Zum Beispiel würde ich in Python, wenn ich ein Wörterbuch drucken wollte, nur print myDict, aber jetzt habe ich zwei andere Optionen. Wie und wann soll ich sie verwenden?



2
Was ist mit NSLog und dem Drucken eines NSDictionary gibt mir nichts Nützliches?
Benutzer

Ab iOS 10.0 wird empfohlen, diese zu verwenden os_log. Bitte sehen Sie meine Antwort unten .
HuaTham

Zusätzlich zur Swift-Dokumentation unter os_log: Versuchen Sie, die vollständige Dokumentation der Objective-C-Seite anzuzeigen. Es ist viel vollständiger .
Honig

Antworten:


758

Ein paar Unterschiede:

  1. printvs println:

    Die printFunktion druckt beim Debuggen von Apps Nachrichten in der Xcode-Konsole.

    Das printlnist eine Variante davon , die in Swift 2 entfernt wurden , und wird verwendet , nicht mehr. Wenn Sie alten Code sehen, der verwendet wird println, können Sie ihn jetzt sicher durch ersetzen print.

    Zurück in Swift 1.x wurden printam Ende der gedruckten Zeichenfolge keine Zeilenumbrüche hinzugefügt, wohingegen printlndies der Fall war . Heutzutage wird jedoch printimmer das Zeilenumbruchzeichen am Ende der Zeichenfolge hinzugefügt. Wenn Sie dies nicht möchten, geben Sie einen terminatorParameter von an "".

  2. NSLog::

    • NSLog ist langsamer;

    • NSLogFügt der Ausgabe einen Zeitstempel und eine Kennung hinzu, während dies printnicht der Fall ist.

    • NSLogAnweisungen werden sowohl in der Gerätekonsole als printauch in der Debugger-Konsole angezeigt, während sie nur in der Debugger-Konsole angezeigt werden.

    • NSLogverwendet printfZeichenfolgen im Stil von -style, z

      NSLog("%0.4f", CGFloat.pi)

      das wird produzieren:

      2017-06-09 11: 57: 55.642328-0700 MyApp [28937: 1751492] 3.1416

  3. Ab iOS 10 / macOS 10.12 gibt es eine dritte Alternative, die os_logTeil des "Unified Logging" -Systems ist (siehe WWDC 2016-Video Unified Logging und Activity Tracing ).

    • Sie müssen importieren, os.logbevor Sie die os_logFunktion verwenden:

      import os.log
    • Gefällt mir NSLog, os_logwerden Nachrichten sowohl an die Xcode-Debugging-Konsole als auch an die Gerätekonsole ausgegeben

    • Sie können jetzt die Felder "Subsystem" und "Kategorie" steuern, die in der Konsolen-App verfügbar sind. Zum Beispiel:

      let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      os_log("url = %@", log: log, url.absoluteString)
      

      Wenn Sie die App über die externe Konsolen-App beobachten, können Sie diese Spalten nicht nur zur Hauptansicht hinzufügen, sondern auch anhand dieser Spalten filtern. Dies ist sehr nützlich, wenn Sie Ihre Debugging-Nachrichten von (a) denen unterscheiden möchten, die von anderen Subsystemen im Auftrag Ihrer App generiert wurden. oder (b) Nachrichten aus anderen Kategorien oder Typen.

    • Sie können verschiedene Arten von Protokollierung Nachrichten angeben, entweder .info, .debug, .error, .fault(oder .default):

      os_log("web service did not respond", type: .error)

      Wenn Sie also die externe Konsolen-App verwenden, können Sie festlegen, dass nur Nachrichten bestimmter Kategorien angezeigt werden (z. B. Debugging-Nachrichten nur anzeigen, wenn Sie im Menü "Aktion" der Konsole "Debug-Nachrichten einschließen" auswählen). Diese Einstellungen bestimmen auch viele subtile Details darüber, ob Dinge auf der Festplatte protokolliert werden oder nicht. Weitere Informationen finden Sie im WWDC-Video.

    • Sie können bei der Verwendung keine Zeichenfolgeninterpolation verwenden os_log. Zum Beispiel können Sie nicht tun:

      os_log("foo \(url.absoluteString)")

      Sie müssten tun:

      os_log("url = %@", url.absoluteString)
    • Einer der Gründe für die oben genannte Einschränkung ist die Unterstützung des Datenschutzes. Primitive Datentypen (z. B. Zahlen) sind standardmäßig öffentlich und Objekte (z. B. Zeichenfolgen) sind standardmäßig privat. Im vorherigen Beispiel, in dem Sie die URL protokolliert haben, wird Folgendes angezeigt, wenn die App vom Gerät selbst aufgerufen wurde und Sie sie über die Konsolen-App Ihres Mac ansehen.

      url = <privat>

      Wenn Sie es von einem externen Gerät aus sehen möchten, müssen Sie Folgendes tun:

      os_log("url = %{public}@", url.absoluteString)
    • Beachten Sie, dass NSLogjetzt das einheitliche Benachrichtigungssystem hinter den Kulissen verwendet wird, jedoch mit den folgenden Einschränkungen:

      • Sie können das Subsystem, die Kategorie oder den Protokolltyp nicht steuern.

      • Datenschutzeinstellungen werden nicht unterstützt.

Unterm Strich printist dies für einfache Aufgaben ausreichend, aber NSLognützlich, da es Zeitstempelinformationen für Sie enthält.

Die Leistung von wird os_logbeim Debuggen von iOS-Apps, die außerhalb von Xcode getestet werden müssen, deutlich erleichtert. Wenn Sie beispielsweise iOS-App-Prozesse im Hintergrund wie das Abrufen im Hintergrund testen, ändert die Verbindung zum Xcode-Debugger den App-Lebenszyklus . Daher möchten Sie häufig auf einem physischen Gerät testen, die App vom Gerät selbst ausführen und die App nicht über den Xcode-Debugger starten. Mit der einheitlichen Protokollierung können Sie Ihre iOS-Geräteanweisungen weiterhin os_logüber die macOS Console-App anzeigen.


37
Schöne Zusammenfassung! Um noch ein paar hinzuzufügen: Sie können einen NSString an println übergeben, nicht jedoch an NSLog. Sie können Argumente für NSLog hinzufügen, aber nicht println. Schnelle String-Interpolation stürzt manchmal für NSLog ab, nicht jedoch für println.
Bao Lei

2
Ein interessanter Hinweis zur Swift-Compiler-Optimierung und zur Verwendung von print () medium.com/ios-os-x-development/…
Carl

@Rob Wenn ich print verwende, wird es dann in der Debugger-Konsole angezeigt oder nicht? Oder sollten wir debugPrint verwenden?

1
Wenn Sie verwenden print, wird es genau wie im Debug-Bereich von Xcode angezeigt debugPrint. Der einzige Unterschied besteht darin, dass printdie descriptionMethode des Objekts aufgerufen wird und debugPrintAufrufe ausgeführt werden debugDescription, die ausführlicher sein können als description.
Rob

@Honey, dieser Kommentarthread wurde als übermäßig lang markiert, daher wollte ich Sie nur daran erinnern, dass Kommentare nicht für erweiterte Diskussions- oder Debugging-Sitzungen vorgesehen sind. Wenn Sie etwas haben, das als Frage gestellt werden kann, die für das Stapelüberlaufformat geeignet ist, stellen Sie es bitte als Frage, damit jeder von seinen Antworten profitieren kann. Wenn es nicht als Frage funktioniert, müssen Sie die Diskussion zum Chatten nehmen. Reservieren Sie Kommentare nur, wenn Sie um Klarstellung bitten oder schnelle Beobachtungen machen möchten.
Cody Gray

80

Wenn Sie Swift 2 verwenden , können Sie jetzt nur print () verwenden, um etwas in die Ausgabe zu schreiben.

Apple hat die Funktionen println () und print () in einer zusammengefasst.

Auf iOS 9 aktualisiert

Standardmäßig beendet die Funktion die gedruckte Zeile durch Hinzufügen eines Zeilenumbruchs.

print("Hello Swift")

Terminator

Übergeben Sie eine leere Zeichenfolge als Abschlusszeichen, um einen Wert ohne Zeilenumbruch danach zu drucken

print("Hello Swift", terminator: "")

Separator

Sie können jetzt Trennzeichen verwenden, um mehrere Elemente zu verketten

print("Hello", "Swift", 2, separator:" ")

Beide

Oder Sie können mit auf diese Weise kombinieren

print("Hello", "Swift", 2, separator:" ", terminator:".")

5
appendNewlinehat einen Standardwert vontrue
Adam

1
In iOS (9.0) müssen Sie terminator : ""zBprint("...", terminator: "")
Khotu Nam

Die Aussage in Ihrem ersten Satz ist falsch. NSLog () funktioniert immer noch, auch in Swift 2.x
Sebastian

62

Darüber hinaus hat Swift 2 debugPrint()(und CustomDebugStringConvertibleProtokoll)!

Vergessen Sie nicht, debugPrint()wie print()es funktioniert, aber am besten zum Debuggen geeignet ist .

Beispiele:

  • Saiten
    • print("Hello World!") wird Hello World
    • debugPrint("Hello World!")wird "Hello World"(Zitate!)
  • Bereiche
    • print(1..<6) wird 1..<6
    • debugPrint(1..<6) wird Range(1..<6)

Jede Klasse kann ihre Darstellung der Debug-Zeichenfolge über das CustomDebugStringConvertibleProtokoll anpassen .


2
DebugPrintableProtokoll wurde in CustomDebugStringConvertibleProtokoll umbenannt .
Franklin Yu

Danke, Franklin!
Valentin Shergin

So Swift descriptionist debugDescriptionals Python strist repr?
BallpointBen

Ja, ich denke schon.
Valentin Shergin

39

Als Ergänzung zu Robs Antwort hat Apple seit iOS 10.0 ein völlig neues "Unified Logging" -System eingeführt, das vorhandene Protokollierungssysteme (einschließlich ASL und Syslog, NSLog) ersetzt und dank seiner neuen Techniken, einschließlich der vorhandenen Protokollierungsansätze, die Leistung übertrifft Protokolldatenkomprimierung und verzögerte Datenerfassung.

Von Apple :

Das einheitliche Protokollierungssystem bietet eine einzige, effiziente und leistungsfähige API für die Erfassung von Nachrichten auf allen Systemebenen. Dieses einheitliche System zentralisiert die Speicherung von Protokolldaten im Speicher und in einem Datenspeicher auf der Festplatte.

Apple empfiehlt dringend os_log, künftig alle Arten von Nachrichten zu protokollieren, einschließlich Informationen, Debugging und Fehlermeldungen, da die Leistung im Vergleich zu früheren Protokollierungssystemen erheblich verbessert wurde und die zentralisierte Datenerfassung eine bequeme Protokoll- und Aktivitätsprüfung für Entwickler ermöglicht. Tatsächlich ist das neue System wahrscheinlich so klein, dass es keinen "Beobachter-Effekt" verursacht, bei dem Ihr Fehler verschwindet, wenn Sie einen Protokollierungsbefehl einfügen, wodurch das Timing des Fehlers beeinträchtigt wird.

Leistung der Aktivitätsverfolgung, jetzt Teil des neuen Unified Logging-Systems

Mehr dazu erfahren Sie hier im Detail .

Um es zusammenzufassen: Verwenden print()Sie es zur Vereinfachung für Ihr persönliches Debugging (die Nachricht wird jedoch nicht protokolliert, wenn sie auf Benutzergeräten bereitgestellt wird). Verwenden Sie dann Unified Logging ( os_log) so oft wie möglich für alles andere.


5

Es gibt eine andere Methode, dump()die auch zum Protokollieren verwendet werden kann:

func dump<T>(T, name: String?, indent: Int, maxDepth: Int, maxItems: Int)

Gibt den Inhalt eines Objekts mithilfe seines Spiegels auf die Standardausgabe aus.

Aus Swift Standard Library-Funktionen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.