iOSアプリ開発でログにログレベルを導入する方法
iOSアプリ開発でログを出力する場合「NSLog」を使用するが、Javaでログ出力に用いられるLog4Jのログレベルの様な考え方は存在しない。
今回はiOSアプリ開発でログにログレベルを導入する方法を紹介する。
<捕捉>
Log4Jのログレベルは、設定値によって出力するログを制御する方式である。
例えば、エラーより深刻なログを出力する設定にした場合、デバッグのために出力するログは出力されない仕組みである。
ログレベルの設定は、設定ファイルで簡単に変更することができ、単体テスト時は全てのログを出力し、結合テストの時は警告以上のログを出力し、サービスイン後はエラー以上のログを出力するといった制御が行える。
<方法概要>
1.PCHファイルにログレベルを定義する
2.PCHファイルに採用するログレベル定義する
3.PCHファイルにログレベル毎のログ出力を定義する
(注意)
PCHファイルはXcode6から自動で生成されなくなった。
手動で作成する方法は「Xcode6でPCHファイルを追加する方法」を参照のこと。
説明を簡単にするため、今回設定するログレベルは、下記の3レベルとする。
<方法詳細>
1.PCHファイルにログレベルを定義する
<プロジェクト名>-Prefix.pchファイルにログレベルを定義する。
数値に意味は無く、他のログレベルと異なるのであれば、任意で良い。
//ログレベル定義 #define VAL_LOG_NONE 0 //ログ無し #define VAL_LOG_ERROR 1 //エラー #define VAL_LOG_DEBUG 2 //デバッグ
2.PCHファイルに採用するログレベル定義する
<プロジェクト名>-Prefix.pchファイルに採用するログレベル定義する。
「DEF_LOG_LEVEL」の右に手順1で定義したログレベルを記述することで、アプリが動作する時に採用するログレベルを定義する。
(下記の例はログレベル「エラー」を設定している)
//ログレベル設定 #define DEF_LOG_LEVEL VAL_LOG_ERROR
3.PCHファイルにログレベル毎のログ出力を定義する
<プロジェクト名>-Prefix.pchファイルにログレベル毎のログ出力を定義する。
マクロのif文で、手順2で設定した採用ログレベルにより、ログ出力の有無を定義する。
デバッグレベルで出力したいログ出力のために識別子「LogD」を定義し、エラーレベルで出力したいログ出力のために識別子「LogE」を定義する。
#if DEF_LOG_LEVEL == VAL_LOG_DEBUG //↓↓↓ ログレベルが「デバッグ」の場合の定義 #define LogD(format, ...) NSLog((@"<D>: "format), ##__VA_ARGS__) //※1 #define LogE(format, ...) NSLog((@"<E>: "format), ##__VA_ARGS__) //※2 #elif DEF_LOG_LEVEL == VAL_LOG_ERROR //↓↓↓ ログレベルが「エラー」の場合の定義 #define LogD(format, ...) //※3 #define LogE(format, ...) NSLog((@"<E>: "format), ##__VA_ARGS__) //※4 #elif DEF_LOG_LEVEL == VAL_LOG_NONE //↓↓↓ ログレベルが「ログ無し」の場合の定義 #define LogD(format, ...) //※5 #define LogE(format, ...) //※6 #endif
※1:「LogD」という識別子を通常の「NSLog」出力に「
※2:「LogE」という識別子を通常の「NSLog」出力に「
※3:「LogD」という識別子は無視する
※4:「LogE」という識別子を通常の「NSLog」出力に「
※5:「LogD」という識別子は無視する
※6:「LogE」という識別子は無視する
自動生成されたPCHファイルか否かで、冒頭部分が異なる。
例は手動で生成したPCHファイルである。
#ifndef LogSample_LogSample_Prefix_pch #define LogSample_LogSample_Prefix_pch //ログレベル定義 #define VAL_LOG_NONE 0 //ログ無し #define VAL_LOG_ERROR 1 //エラー #define VAL_LOG_DEBUG 2 //デバッグ //ログレベル設定 #define DEF_LOG_LEVEL VAL_LOG_ERROR #if DEF_LOG_LEVEL == VAL_LOG_DEBUG //↓↓↓ ログレベルが「デバッグ」の場合の定義 #define LogD(format, ...) NSLog((@"<D>: "format), ##__VA_ARGS__) //※1 #define LogE(format, ...) NSLog((@"<E>: "format), ##__VA_ARGS__) //※2 #elif DEF_LOG_LEVEL == VAL_LOG_ERROR //↓↓↓ ログレベルが「エラー」の場合の定義 #define LogD(format, ...) //※3 #define LogE(format, ...) NSLog((@"<E>: "format), ##__VA_ARGS__) //※4 #elif DEF_LOG_LEVEL == VAL_LOG_NONE //↓↓↓ ログレベルが「ログ無し」の場合の定義 #define LogD(format, ...) //※5 #define LogE(format, ...) //※6 #endif #endif
<使用方法>
ログを出力する際は、「NSLog」ではなく、「LogD」および「LogE」を使用する。
サンプルコードを下記に示す。
- (void)viewDidLoad { [super viewDidLoad]; LogD(@"デバッグレベルのログ"); LogE(@"エラーレベルのログ"); NSLog(@"NSLogによる出力"); }
<出力結果>
「#define DEF_LOG_LEVEL VAL_LOG_DEBUG」と設定した場合
2014-12-01 20:48:28.543 LogSample[4775:32404] <D>: デバッグレベルのログ 2014-12-01 20:48:28.544 LogSample[4775:32404] <E>: エラーレベルのログ 2014-12-01 20:48:28.545 LogSample[4775:32404] NSLogによる出力
「#define DEF_LOG_LEVEL VAL_LOG_ERROR」と設定した場合
2014-12-01 20:49:35.280 LogSample[4861:32974] <E>: エラーレベルのログ 2014-12-01 20:49:35.281 LogSample[4861:32974] NSLogによる出力
ソースコードを変更せずに、PCHファイルの変更で、デバッグレベルのログが出力されなくなった。
「#define DEF_LOG_LEVEL VAL_LOG_NONE」と設定した場合
2014-12-01 20:51:42.142 LogSample[4991:33935] NSLogによる出力
ソースコードを変更せずに、PCHファイルの変更で、デバッグレベル・エラーレベルのログが出力されなくなった。
<考察>
実用レベルのiOSアプリを作成する場合、ログ出力のためのコードが大量になることが少なくない。
リリース時に全てログ出力用のコードを削除しても良いが、アプリにトラブルが発生した時に原因調査に再びログ出力用コードを記述することになる。
今回紹介した方法を使用すれば、簡単にログ出力量を制御することができる。
Enjoy Programing!!
<関連記事>
iOSアプリ開発でログにクラス名とメソッド名を出力する方法
iOSアプリ開発でログにログレベルを導入する方法(本記事)
iOSアプリ開発でNSErrorの情報を出力する拡張NSLogを定義する方法
<お勧め書籍>