繁体   English   中英

如何禁用日志记录?

[英]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 withSysLogBannerBOOL 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有所不同,因为如果我们尝试传递nilnil指针,编译器将抱怨类型不匹配(在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM