落とし穴、というかパースする前にはnilチェックしましょうと言う話。
iOS5からJSONを便利に扱えるNSJSONSerializationクラスだが、JSONをパースするためのJSONObjectWithData:options:error:メソッドは、引数として渡すNSDataがnilだと例外を発生させる。
//パースさせたいNSDataがnilの場合例外が発生する
id jsonObject = [NSJSONSerialization JSONObjectWithData:nil
options:NSJSONReadingAllowFragments
error:nil];
引数にNSErrorのアドレスを渡すことでエラーがセットされるが、これはあくまでパースエラーが起こった場合であり、パースさせたい対象がnilだとパースエラーではなく例外が発生するためにこのエラーでは判断できない。
例外が発生するのならばtry catchで囲むことを考える
id jsonObject;
@try {
jsonObject = [NSJSONSerialization JSONObjectWithData:nil
options:NSJSONReadingAllowFragments
error:nil];
@catch (NSException *exception) {
/*…*/
}
try catchにより例外発生時に強制終了することはなくなったが、nilの場合に例外が発生していると原因が特定されていて防げるのであれば、下記のようにnilチェックをするだけでよいのではないか
if (data) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:nil];
/*…*/
} else {
/*…*/
}
また、try catchをあまり使いたくない理由としては、例外発生時にcatchできようが、tryのコードブロック(スコープ)を抜けてしまうことでコード末尾に辿りつけず、ARC使用時に自動で挿入されたreleaseが実行されないためメモリリークしてしまうため(そのような状況を防ぐにはLLVM コンパイラーのオプションとして "-fobjc-arc-exceptions" につけると良いらしい)。
参考
EZ-NET: 例外発生時の ARC 制御
http://program.station.ez-net.jp/special/objective-c/llvm/arc/exception.asp
Google Objective-Cスタイルガイド 日本語訳
http://www.textdrop.net/google-styleguide-ja/objcguide.xml#Avoid_Throwing_Exceptions