Warnung: Diese Antwort verwendet den privaten-nicht-Art-of dokumentierte Cocoa C-Funktionen _NSSetLogCStringFunction()
und _NSLogCStringFunction()
.
_NSSetLogCStringFunction()
ist eine Schnittstelle, die von Apple erstellt wurde, um die Implementierungsfunktion für NSLog
zu behandeln. Anfänglich war es für WebObjects verfügbar, dass es sich in NSLog
Anweisungen auf Windows-Rechnern einklinkte, aber heute noch in den iOS- und OS X-APIs existiert. Es ist in Support-Artikel dokumentiert.
Die Funktion nimmt in einem Funktionszeiger mit den Argumenten const char* message
, um die Zeichenfolge einzuloggen, unsigned length
, die Länge der Nachricht und ein BOOL withSysLogBanner
, die das Standard-Logging-Banner schaltet. Wenn wir unsere eigene Hook-Funktion für die Protokollierung erstellen, die eigentlich gar nichts macht (eine leere Implementierung anstattwie zB NSLog
), können wir effektiv die gesamte Protokollierung für Ihre Anwendung deaktivieren.
Objective-C Beispiel (oder Swift mit verbrückenden Header):
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
static void hookFunc(const char* message, unsigned length, BOOL withSysLogBanner) { /* Empty */ }
// Later in your application
_NSSetLogCStringFunction(hookFunc);
NSLog(@"Hello _NSSetLogCStringFunction!\n\n"); // observe this isn't logged
eine beispielhafte Implementierung dieses in YILogHook gefunden werden kann, die eine Schnittstelle bietet eine Reihe von Blöcken in jedem NSLog
Anweisung hinzuzufügen (schreiben Datei usw.).
Reines Swift Beispiel:
@asmname("_NSSetLogCStringFunction") // NOTE: As of Swift 2.2 @asmname has been renamed to @_silgen_name
func _NSSetLogCStringFunction(_: ((UnsafePointer<Int8>, UInt32, Bool) -> Void)) -> Void
func hookFunc(message: UnsafePointer<Int8>, _ length: UInt32, _ withSysLogBanner: Bool) -> Void { /* Empty */ }
_NSSetLogCStringFunction(hookFunc)
NSLog("Hello _NSSetLogCStringFunction!\n\n"); // observe this isn't logged
In Swift, können Sie wählten auch ohne hookFunc
wie so mit all den Blockparameter zu ignorieren:
_NSSetLogCStringFunction { _,_,_ in }
zu drehen, um wieder mit objektiv-Anmeldung C, geben Sie einfach NULL
als Funktionszeiger ein:
Mit Swift sind die Dinge etwas anders, da der Compiler sich über einen Typenkonflikt beklagen wird, wenn wir versuchen, nil
oder einen nil
Zeiger (NULL
ist in Swift nicht verfügbar) zu übergeben. Um dies zu beheben, müssen wir auf eine andere Systemfunktion, _NSLogCStringFunction
, zugreifen, um einen Zeiger auf die Standardprotokollimplementierung zu erhalten, diese Referenz beizubehalten, während die Protokollierung deaktiviert ist, und die Referenz zurücksetzen, wenn wir die Protokollierung wieder aktivieren möchten.
Ich habe die Swift Umsetzung dieses gereinigt durch Zugabe einer NSLogCStringFunc
typedef
:
/// Represents the C function signature used under-the-hood by NSLog
typealias NSLogCStringFunc = (UnsafePointer<Int8>, UInt32, Bool) -> Void
/// Sets the C function used by NSLog
@_silgen_name("_NSSetLogCStringFunction") // NOTE: As of Swift 2.2 @asmname has been renamed to @_silgen_name
func _NSSetLogCStringFunction(_: NSLogCStringFunc) -> Void
/// Retrieves the current C function used by NSLog
@_silgen_name("_NSLogCStringFunction")
func _NSLogCStringFunction() -> NSLogCStringFunc
let logFunc = _NSLogCStringFunction() // get function pointer to the system log function before we override it
_NSSetLogCStringFunction { (_, _, _) in } // set our own log function to do nothing in an anonymous closure
NSLog("Observe this isn't logged.");
_NSSetLogCStringFunction(logFunc) // switch back to the system log function
NSLog("Observe this is logged.")
Gelöschte meiner Antwort.Soweit ich weiß, ist es unmöglich, NSLog kurzzuschließen, aber lassen Sie uns hoffen, dass jemand mir das Gegenteil beweisen wird ... – deadbeef
@deadbeef Vielen Dank für Ihren Rat und das Löschen "es ist nicht möglich" asnwer. Ich betrachte Ihre Reaktionen als vorbildlich SO Benutzer, aber ich hoffe, dass Sie sich in diesem Fall irren und jemand wird eine Lösung/Abhilfe finden. Das Gegenteil wäre eine sehr schlechte Nachricht für mich. – drasto
Mögliches Duplikat von [NSLog-Ausgabe aus vorkompilierter Bibliothek ausblenden] (http://stackoverflow.com/questions/12608988/hiding-nslog-output-coming-from-precompiled-library). Es gibt - soweit ich weiß - keine Möglichkeit, * NSLog in kompiliertem Code * zu deaktivieren (wie in Apples Bibliotheken), * das Umleiten von * stderr scheint die einzige Lösung zu sein. –