どうも。
uncaught exceptionで異常終了した際に、
その内容が確認出来ると便利。
まぁ、
Xcodeにつないで実機動作中であれば、
コンソールに多少の情報が出て、
それだけでも解決に至ることも多いですが。
ファイルに出しておけば、
XcodeでRunしていなくても取り出して確認できるし、
NSUserDefaultに保存しておけば、
次回起動時に異常終了があったことも検知することもできる。
実現するには、
「NSSetUncaughtExceptionHandler関数にハンドラ関数のアドレスを渡す」
これがちょっと面倒というか、
C言語的なんだけど。
ハンドラ関数を作成して、
そのアドレスを渡してやることで、
例外発生時の動作を定義出来る。
とりあえず、
ファイル保存をするとして。
AppDelegate内に、
下記のような関数を定義しておく。
※関数のプロトタイプも必要です!
(AppDelegateの頭の方にでも書いておけばOK)
// 例外発生時の情報を出力
void uncaughtExceptionHandler(NSException *exception)
{
NSString *exceptionOccur = @"\n***** Uncaught exception occured!*****";
// 例外の名前
NSString *exceptionName = [NSString stringWithFormat:@"exception name:%@",
[exception name]];
// 例外の理由
NSString *exceptionReason = [NSString stringWithFormat:@"exception reason:%@",
[exception reason]];
// 例外のコールスタック
NSString *exceptionCallStack = [NSString stringWithFormat:@"exception callStackSymbols:\n%@\n",
[exception callStackSymbols]];
// ログファイルに書き出す内容
NSString *exceptionLog = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n",
exceptionOccur, exceptionName, exceptionReason, exceptionCallStack];
// デバッグコンソールにも出力
NSLog(@"\n%@", exceptionLog);
NSString *exceptionLogDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES)
objectAtIndex:0];
NSString *exceptionLogPath = [exceptionLogDir
stringByAppendingPathComponent:@"uncaughtException.log"];
NSError *error = nil;
// ファイルに書き込み
[exceptionLog writeToFile:exceptionLogPath
atomically:NO
encoding:NSUTF8StringEncoding
error:&error];
if (error) {
LOG(@"Cannot write exception log file!!");
}
// もしNSUserDefaultsに保存したいならこんな感じ
//[[NSUserDefaults standardUserDefaults] setValue:exceptionLog
// forKey:@"exceptionLog"];
}
void uncaughtExceptionHandler(NSException *exception)
{
NSString *exceptionOccur = @"\n***** Uncaught exception occured!*****";
// 例外の名前
NSString *exceptionName = [NSString stringWithFormat:@"exception name:%@",
[exception name]];
// 例外の理由
NSString *exceptionReason = [NSString stringWithFormat:@"exception reason:%@",
[exception reason]];
// 例外のコールスタック
NSString *exceptionCallStack = [NSString stringWithFormat:@"exception callStackSymbols:\n%@\n",
[exception callStackSymbols]];
// ログファイルに書き出す内容
NSString *exceptionLog = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n",
exceptionOccur, exceptionName, exceptionReason, exceptionCallStack];
// デバッグコンソールにも出力
NSLog(@"\n%@", exceptionLog);
NSString *exceptionLogDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES)
objectAtIndex:0];
NSString *exceptionLogPath = [exceptionLogDir
stringByAppendingPathComponent:@"uncaughtException.log"];
NSError *error = nil;
// ファイルに書き込み
[exceptionLog writeToFile:exceptionLogPath
atomically:NO
encoding:NSUTF8StringEncoding
error:&error];
if (error) {
LOG(@"Cannot write exception log file!!");
}
// もしNSUserDefaultsに保存したいならこんな感じ
//[[NSUserDefaults standardUserDefaults] setValue:exceptionLog
// forKey:@"exceptionLog"];
}
んで、
AppDelegate.mの、
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
の中で、
// エラー追跡用の機能を追加する。
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
と書いておけば、
やりたいことが実現出来る。
ログの内容や形式は、
必要に応じて替えればいいです。
それでは。
ちゃお☆
まこぴー。