Skip to content

Instantly share code, notes, and snippets.

@satoshin2071
Last active August 30, 2017 01:57
Show Gist options
  • Save satoshin2071/9778283 to your computer and use it in GitHub Desktop.
Save satoshin2071/9778283 to your computer and use it in GitHub Desktop.
[ObjcC] NSLogをコンソールとファイル両方に出力する
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "SBCLogUtil.h"
#endif
#import "SBCLogUtil.h"
#include <pthread.h>
@implementation SBCLogUtil
void SBCLog(NSString *format, ...)
{
// ファイル名用formatter
NSDateFormatter *fileNameFormatter = [[NSDateFormatter alloc]init];
fileNameFormatter.calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
fileNameFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
[fileNameFormatter setDateFormat:@"yyyyMMdd"];
// ログ時刻用formatter
NSDateFormatter *logFormatter = [[NSDateFormatter alloc]init];
logFormatter.calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
logFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
[logFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss.SSS"];
NSString *createdDate = [fileNameFormatter stringFromDate:[NSDate date]];
NSString *logDate = [logFormatter stringFromDate:[NSDate date]];
// ファイルパス準備
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filename = [NSString stringWithFormat:@"%@_log.txt",createdDate];
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logDirctoryPath = [documentsDirectory stringByAppendingString:@"/logs"];
if (![fileManager fileExistsAtPath:logDirctoryPath]) {
[fileManager createDirectoryAtPath:logDirctoryPath withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *path = [logDirctoryPath stringByAppendingPathComponent:filename];
static FILE *file = NULL;
if (file == NULL) {
// 一週間以上前のログあれば削除
NSDate *todayDate = [NSDate date];
NSArray *allFileNames = [fileManager contentsOfDirectoryAtPath:logDirctoryPath error:NULL];
for(NSString *fileName in allFileNames){
NSString *dateString = [fileName substringToIndex:8];
NSDate *tmpDate = [fileNameFormatter dateFromString:dateString];
NSTimeInterval since = [todayDate timeIntervalSinceDate:tmpDate];
if( (int)((int)since / (60*60*24)) > 7 ){
[fileManager removeItemAtPath:[NSString stringWithFormat:@"%@/%@",logDirctoryPath,fileName] error:NULL];
}
}
// 書き込み用ファイルopen
file = fopen([path cStringUsingEncoding:NSASCIIStringEncoding], "a+");
}
va_list args;
va_start(args, format);
// stderr にログを出す
NSLogv(format, args);
// ファイルにログを出す
// 末尾に改行なかったら入れる
if (![format hasSuffix:@"\n"]) {
format = [format stringByAppendingString:@"\n"];
}
NSString *body = [[NSString alloc]initWithFormat:format arguments:args];
// プロセスIDを取得
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
int processID = [processInfo processIdentifier];
// スレッドIDを収得
mach_port_t machTID = pthread_mach_thread_np(pthread_self());
// NSLogと同じ文章の形にする
NSString *log = [NSString stringWithFormat:@"%@ [%d:%x] %@",logDate, processID,machTID,body];
fputs([log cStringUsingEncoding: NSUTF8StringEncoding],file);
fflush(file);
va_end(args);
}
}
@end
@satoshin2071
Copy link
Author

NSLogと完全にすげ替えたいときはprefix.pchに下記defineで

define NSLog(...) SBCLog(VA_ARGS);

@kzthrk
Copy link

kzthrk commented Aug 30, 2015

すみません、ログに出力されるタイムスタンプが12時間表記になっていませんでしょうか。

私自身はプログラマではなくSEでして、その場限りのコードばかり書いる身なので非常に参考になりました。他の言語に触れた今にして思えば、C言語の奇妙な?staticの挙動を思い出しました。

ロジックの骨格はC言語で、ステートメントの大半がObjective-Cという想像していなかったコードに出会っておもしろかったです。(勝手にシングルトンのクラスを想像していたので...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment