如何禁用日志记录? [英] How to disable logging?

查看:698
本文介绍了如何禁用日志记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序正在使用Apple提供的 UITextChecker 类。这个类有以下错误:如果iOS设备离线(预计通常是我的应用程序),每次我调用一些 UITextChecker 的方法时,它会记录到控制台:

I have an app that is making use of UITextChecker class provided by Apple. This class has a following bug: If the iOS device is offline (expected to be often for my app) each time I call some of UITextCheckers methods it logs following to console:

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 方法之前禁用日志记录,然后重新启用它。或者是否有任何方法可以选择性地禁用每个类的日志记录(如果基础类不是我的,则为事件)?或者任何其他解决方案?

I do not want to have logs spammed by this messages. Is there a way to disable logging from code? I would disable logging before call to any of UITextCheckers methods and reenable it afterwards. Or is there perhaps any way how to disable logging selectively per class (event if it is foundation class not mine)? Or any other solution?

推荐答案

警告:这个答案使用私有排序-documented Cocoa C函数 _NSSetLogCStringFunction() _NSLogCStringFunction()

Warning: This answer uses the private-yet-sort-of-documented Cocoa C functions _NSSetLogCStringFunction() and _NSLogCStringFunction().

_NSSetLogCStringFunction()是Apple创建的一个接口,用于处理 NSLog 的实现功能。最初暴露给WebObjects挂钩到Windows机器上的 NSLog 语句,但今天仍然存在于iOS和OS X API中。它在支持文章中有记录。

_NSSetLogCStringFunction() is an interface created by Apple to handle the implementation function for NSLog. It was initially exposed for WebObjects to hook into NSLog statements on Windows machines, but still exists in the iOS and OS X APIs today. It is documented in this support article.

该函数接受一个函数指针,其参数为 const char * message ,要记录的字符串,无符号长度,消息的长度,以及切换标准日志记录横幅的 BOOL withSysLogBanner 。如果我们为日志创建我们自己的钩子函数实际上没有做任何事情(空实现而不是调用 fprintf ,如 NSLog 幕后操作),我们可以有效地禁用你的应用程序的所有日志记录。

The function takes in a function pointer with the arguments const char* message, the string to log, unsigned length, the length of the message, and a BOOL withSysLogBanner which toggles the standard logging banner. If we create our own hook function for logging that doesn't actually do anything (an empty implementation rather than calling fprintf like NSLog does behind-the-scenes), we can effectively disable all logging for your application.

Objective-C示例(或带有桥接头的Swift):

Objective-C Example (or Swift with bridging 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

此示例的实现可以在 YILogHook ,它提供了一个接口,可以将块数组添加到任何 NSLog 声明(写入文件等)。

An example implementation of this can be found in YILogHook, which provides an interface to add an array of blocks to any NSLog statement (write to file, etc).

Pure Swift示例:

Pure Swift Example:

@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 的参数如下:

In Swift, you can also chose to ignore all of the block parameters without using hookFunc like so:

_NSSetLogCStringFunction { _,_,_ in }

要使用Objective-C重新开启记录,只需传入 NULL 作为函数指针:

To turn logging back on using Objective-C, just pass in NULL as the function pointer:

_NSSetLogCStringFunction(NULL);

使用Swift的情况有点不同,因为如果我们尝试将编译器抱怨类型不匹配传入 nil nil 指针( NULL 不可用在斯威夫特)。要解决此问题,我们需要访问另一个系统函数 _NSLogCStringFunction ,以获取指向默认日志记录实现的指针,在禁用日志记录时保留该引用,并将引用设置为当我们想要重新开启日志时。

With Swift things are a little different, since the compiler will complain about a type mismatch if we try to pass in nil or a nil pointer (NULL is unavailable in Swift). To solve this, we need to access another system function, _NSLogCStringFunction, to get a pointer to the default logging implementation, retain that reference while logging is disabled, and set the reference back when we want to turn logging back on.

我通过添加 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.")

这篇关于如何禁用日志记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆