[英]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.