NSLogはOSからの警告などが表示されるので非表示にしたくないが、3rd partyのライブラリのdebug logなどノイズが多いのでfilterしたい。
_NSSetLogCStringFunctionというprivate APIがあるようだが、Xcode上ではうまくいかなかった。
代替案としてstderrをpipeにリダイレクトしてみた。
元のstderrのハンドルを保存しておけば、Xcodeのconsoleに出力しつつ端末のファイルに残す、みたいなことができると思う。
以下の例では+loadにより明示的にnewしなくても勝手に起動する。
StdErrFilter.m
#import <UIKit/UIKit.h>
#ifdef DEBUG
static dispatch_source_t dispatchSource;
@interface StdErrFilter : NSObject
@end
@implementation StdErrFilter
+ (void)load
{
NSPipe *pipe = [NSPipe new];
int stdErrHandle = dup(STDERR_FILENO);
dup2(pipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO);
dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ,
pipe.fileHandleForReading.fileDescriptor,
0,
dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0));
dispatch_source_set_event_handler(dispatchSource, ^{
NSData *data = pipe.fileHandleForReading.availableData;
const char *bytes = data.bytes;
size_t length = 0, remainBytes;
for (remainBytes = data.length; remainBytes > 0; remainBytes -= length) {
const char *lf = strchr(bytes, '\n');
length = lf ? lf - bytes + 1 : remainBytes;
// TODO: filter
write(stdErrHandle, bytes, length);
bytes += length;
}
});
dispatch_resume(dispatchSource);
}
@end
#endif