Good By NSLog ~ CocoaLumberjack 2.x.x ~
CocoaLumberJack
iOS には CocoaLumberJack というログライブラリがあります。Java でいう Log4J のようなものです。ログの出力レベルがあり、コンソールやファイルにログを出力できます。もちろんログフォーマットも自由にカスタマイズできます。このライブラリを使うことで、アプリを実機で検証しているときにアプリクラッシュ時のログが追いやすくなり、不具合改修時の手助けになってくれることを個人的には期待しています。
ログ出力レベル
- DDLogLevelError
- DDLogLevelWarning
- DDLogLevelInfo
- DDLogLevelDebug
- DDLogLevelVerbose
- DDLogLevelOff
インストール
pod 'CocoaLumberjack','~> 2.0.1'
設定
import
*-Prefix.pch に書いておくのが楽です。 デバックビルドでは出力レベルを低く設定、リリースビルドでは出力しないようにしています。
#ifdef __OBJC__ #define LOG_LEVEL_DEF ddLogLevel #import <CocoaLumberjack/CocoaLumberjack.h> #ifdef DEBUG static const DDLogLevel ddLogLevel = DDLogLevelVerbose; #else static const DDLogLevel ddLogLevel = DDLogLevelOff; #endif #endif
コンソール出力時のカスタムフォーマット
コンソールに吐き出す際のフォーマットをカスタマイズします。ここでは LogFormatter クラスを新規で作成。
#import <UIKit/UIKit.h> @interface LogFormatter : NSObject <DDLogFormatter> @end
ログレベルと、どのクラスの何行目で吐いているか出力するようにしています。
#import "LogFormatter.h" @implementation LogFormatter - (NSString *)formatLogMessage:(DDLogMessage *)logMessage; { NSString *logLevel; switch (logMessage.flag) { case DDLogFlagError : logLevel = @"error"; break; case DDLogFlagWarning : logLevel = @"warn"; break; case DDLogFlagInfo : logLevel = @"info"; break; case DDLogFlagDebug : logLevel = @"debug"; break; default : logLevel = @"verbose"; break; } NSDateFormatter *format = [[NSDateFormatter alloc] init]; [format setDateFormat:@"yyyy/MM/dd HH:mm:ss"]; NSString *dateTime = [format stringFromDate:[NSDate date]]; NSString *threadID = logMessage.threadID; NSString *fileName = logMessage.fileName; NSInteger lineNumber = logMessage.line; NSString *message = logMessage.message; return [NSString stringWithFormat:@"%@ (%@) %@ [%@(%ld)] %@", dateTime, threadID, logLevel, fileName, lineNumber, message]; } @end
AppDelegate での読み込み
AppDelegate に以下を追加。ここではコンソールとファイルに吐き出すための記述をしています。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Console Log DDTTYLogger *logger = [DDTTYLogger sharedInstance]; logger.logFormatter = [[MfLogFormatter alloc] init]; [DDLog addLogger:logger]; // File Log NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPathStr = paths[0]; NSString *filePath = [documentPathStr stringByAppendingString:@"/MFLog"]; DDLogFileManagerDefault *fileManager = [[DDLogFileManagerDefault alloc] initWithLogsDirectory:filePath]; DDFileLogger *fileLogger = [[DDFileLogger alloc] initWithLogFileManager:fileManager]; [DDLog addLogger:fileLogger]; return YES; }
ログ出力
適当に以下のようなログを出力します。
DDLogError(@"error log"); DDLogWarn(@"warn log"); DDLogInfo(@"info log"); DDLogDebug(@"debug log");
コンソール
先ほどのカスタムフォーマットが適用されこんな感じになります。どのクラス(SampleViewController)の何行目で吐かれたかもちゃんと表示されています。
2015/07/07 18:39:46 (381577) error [SampleViewController(182)] error log 2015/07/07 18:39:46 (381577) warn [SampleViewController(183)] warn log 2015/07/07 18:39:46 (381577) info [SampleViewController(184)] info log 2015/07/07 18:39:46 (381577) debug [SampleViewController(185)] debug log
ちなみにこれまでの NSLog だとこんな感じです。
2015-07-07 18:43:13.015 SampleProject[34394:385270] error log 2015-07-07 18:43:13.015 SampleProject[34394:385270] warn log 2015-07-07 18:43:13.016 SampleProject[34394:385270] info log 2015-07-07 18:43:13.016 SampleProject[34394:385270] debug log
ファイル
AppDelegate で /Documents 配下を指定しているので、/Documents 配下に log ファイルが配置されます。 今はデフォルト設定でファイル出力していますが、ファイル名や拡張子は好きに変更できます。
まとめ
ログの設定がだいぶ柔軟に行えるようになるかと思います。 ログ周りを整備するだけでもだいぶ開発が捗ります。