2016-03-09 25 views
5

Ich habe eine App, die UITextChecker Klasse von Apple zur Verfügung stellt. Diese Klasse hat einen folgenden Fehler: Wenn das iOS-Gerät offline ist (voraussichtlich oft für meine Anwendung sein) jedes Mal, wenn ich einige UITextChecker s Methoden aufrufen, meldet es sich folgende trösten:Wie kann ich die Protokollierung deaktivieren?

2016-03-08 23:48:02.119 HereIsMyAppName [4524:469877] UITextChecker sent string:isExemptFromTextCheckerWithCompletionHandler: to com.apple.TextInput.rdt but received error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.TextInput.rdt was invalidated." 

Ich will nicht haben, protokolliert Spam durch diese Nachrichten. Gibt es eine Möglichkeit, die Protokollierung von Code zu deaktivieren? Ich würde die Protokollierung vor dem Aufruf einer der UITextChecker Methoden deaktivieren und danach wieder aktivieren. Oder gibt es vielleicht eine Möglichkeit, die Protokollierung selektiv für jede Klasse zu deaktivieren (Ereignis, wenn es sich um eine Basisklasse handelt, nicht um meine)? Oder irgendeine andere Lösung?

+2

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

+0

@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

+1

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. –

Antwort

9

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 NSLogCStringFunctypedef:

/// 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.") 
+0

Das ist unglaublich !! Schauen Sie sich [this] (https://github.com/cjwl/cocotron/blob/master/Foundation/NSObjCRuntime.m) an! Es ist alles da, also können Sie es deaktivieren und später wieder aktivieren. – deadbeef

+0

Das einzige Problem ist, dass es eine private API ist, also nutze deine eigenen Risiken ... – deadbeef

+0

@deadbeef Ja, das hab ich auch gefunden. Das zeigt Ihnen Apples Implementierung der Protokollierung. Sie können einen eigenen Funktionszeiger angeben, um die 'NSLog'-Implementierung zu ändern. Überprüfen Sie 'NSPlatformLogString' in ['NSPlatform'] (https://github.com/cjwl/cocotron/blob/master/Foundation/platform_posix/NSPlatform_posix.m). – JAL

Verwandte Themen