[英]How to disable logging?
我有一個使用Apple提供的UITextChecker
類的應用程序。 此類有以下錯誤:如果iOS設備每次我調用UITextChecker
的某些方法都脫機時(預期對於我的應用程序來說經常如此),它將記錄到控制台:
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."
我不希望此郵件發送垃圾郵件。 有沒有辦法禁用代碼日志記錄? 我將在調用UITextChecker
的任何方法之前禁用日志記錄,然后再啟用它。 還是有什么辦法可以有選擇地禁用每個類的日志記錄(如果是基礎類而不是我的,則會發生事件)? 或其他解決方案?
警告 :此答案使用了尚未公開的可可C函數_NSSetLogCStringFunction()
和_NSLogCStringFunction()
。
_NSSetLogCStringFunction()
是Apple創建的用於處理NSLog
的實現功能的接口。 WebObjects最初暴露給Windows機器上的NSLog
語句,但如今仍存在於iOS和OS X API中。 此支持文章中對此進行了記錄。
該函數接收帶有參數const char* message
,要記錄的字符串, unsigned length
,消息的長度以及帶有BOOL withSysLogBanner
的BOOL withSysLogBanner
的函數指針,該BOOL withSysLogBanner
切換標准日志記錄BOOL withSysLogBanner
的信息。 如果我們創建自己的鈎子函數來進行日志記錄,而實際上它並沒有做任何事情(一個空的實現,而不是像NSLog
那樣在幕后調用fprintf
),那么我們可以有效地禁用應用程序的所有日志記錄。
Objective-C示例(或帶有橋接頭的Swift):
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
可以在YILogHook中找到此示例的實現,它提供了一個接口,用於將塊數組添加到任何NSLog
語句(寫入文件等)。
純Swift示例:
@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
在Swift中,您還可以選擇忽略所有塊參數,而無需使用hookFunc
如下所示:
_NSSetLogCStringFunction { _,_,_ in }
要使用Objective-C重新登錄,只需傳入NULL
作為函數指針:
_NSSetLogCStringFunction(NULL);
與Swift有所不同,因為如果我們嘗試傳遞nil
或nil
指針,編譯器將抱怨類型不匹配(在Swift中NULL
不可用)。 為了解決這個問題,我們需要訪問另一個系統函數_NSLogCStringFunction
,以獲取指向默認日志記錄實現的指針,在禁用日志記錄時保留該引用,並在希望重新打開日志記錄時將其設置回。
我通過添加NSLogCStringFunc
typedef
清理了Swift的實現:
/// 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.")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.