NSJSONSerialization
を使用して Web サービスからの JSON 応答を解析した後+isKindOfClass:
、サーバーが予期した種類のデータを返したことを確認します。この方法を使用すると、いくつかの奇妙な動作に遭遇しました。例を使用して説明します。
次のオブジェクトを検討してください。
// Definitions
NSDictionary *son = @{ @"firstname" : @"James", @"lastname" : @"Appleseed" };
NSDictionary *daughter = @{ @"firstname" : @"Susan", @"lastname" : @"Appleseed"};
NSArray *children = @[son, daughter];
NSDictionary *father = @{ @"firstname" : @"John", @"lastname" : @"Appleseed" };
NSDictionary *family = @{@"children" : children, @"father" : father};
NSDictionary *pedigree = @{@"family" : family };
これらのオブジェクトは、サーバーから返された逆シリアル化された JSON を表します。ここで、子の配列を使用して、NSArray の を使用して子の数を計算したい場合-count
は、子オブジェクトが NSArray であることを確認する必要があります。たとえば、子オブジェクトがたまたま文字列である場合、アプリは配列を期待していますが、文字列はcount
メソッドを実装していないため、アプリはクラッシュします。説明したチェックを実装する次のコード シーケンスを検討してください。
// First test
id _family = [pedigree objectForKey:@"family"];
if ([_family isKindOfClass:[NSDictionary class]])
{
NSDictionary *_family = (NSDictionary *)_family;
id _children = [_family objectForKey:@"children"];
NSLog(@"Children: %@", _children);
NSLog(@"Children classname: %@", NSStringFromClass(children.class));
if ([_children isKindOfClass:[NSArray class]]) {
NSLog(@"Children is an NSArray");
} else {
NSLog(@"Children is not an NSArray");
}
} else {
NSLog(@"Family is not an NSDictionary");
}
このコードを実行すると、コンソールに次のように出力されます。
Children: (null)
Children classname: __NSArrayI
Children is not an NSArray
コンソール出力は非常に注目に値し、矛盾しているようにさえ見えます。クラス名が __NSArrayI であるのに、どうして子が NSArray にならないのでしょうか?
少しデバッグした後、この問題を解決するには 2 つの方法があることがわかりました。
- この行を削除
NSDictionary *_family = (NSDictionary *)_family;
_family
キャストされた変数とは異なる名前を使用する
この動作はどのように説明できますか?